【问题标题】:What is the best way to call a script from another script? [closed]从另一个脚本调用脚本的最佳方法是什么? [关闭]
【发布时间】:2009-07-27 06:52:48
【问题描述】:

我有一个名为test1.py 的脚本不在模块中。它只有在脚本本身运行时应该执行的代码。没有函数、类、方法等。我有另一个作为服务运行的脚本。我想从作为服务运行的脚本调用test1.py

例如:

文件test1.py

print "I am a test"
print "see! I do nothing productive."

文件service.py

# Lots of stuff here
test1.py # do whatever is in test1.py

我知道一种方法是打开文件、读取内容并基本上评估它。我假设有更好的方法来做到这一点。或者至少我希望如此。

【问题讨论】:

标签: python


【解决方案1】:

这在 Python 2 中是可能的

execfile("test2.py")

如果对您的情况很重要,请参阅documentation 以了解命名空间的处理。

在 Python 3 中,这可以使用(感谢 @fantastory)

exec(open("test2.py").read())

但是,您应该考虑使用不同的方法;你的想法(据我所知)看起来不太干净。

【讨论】:

  • 直接我在 python 32 中需要的是 exec(open('test2.py').read())
  • 此方法在调用命名空间内执行脚本。 :)
  • 要将命令行参数传递给脚本,您可以编辑sys.argv 列表。
  • 对 Python 3 等价物的更全面处理:stackoverflow.com/questions/436198/…
  • 这不接受参数(要传递给 PY 文件)!
【解决方案2】:

执行此操作的通常方法如下所示。

test1.py

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

service.py

import test1

def service_func():
    print 'service func'

if __name__ == '__main__':
    # service.py executed as script
    # do something
    service_func()
    test1.some_func()

【讨论】:

  • 如果test1.py 位于某个遥远的目录怎么办?
  • 但这并不能真正回答问题,是吗?您不是在执行整个脚本,而是在您导入的脚本中执行一些函数。
  • @GennaroTedesco:你错了。 service.py 中的 import test1 确实执行了 whole 脚本(它只定义了some_func(),因为在这种情况下__name__ == '__main__' 将是False)。这听起来像是所有OP想要做的。这个答案超出了这个范围,但确实回答了这个问题——然后是一些。
  • 如果test1.py 不包含函数some_func() 的定义(而只是一些代码行,例如print("hello")),那么您的代码将无法工作。在这个特定的示例中,它确实有效,因为您实际上是在导入一个外部函数,然后您会回调该函数。
【解决方案3】:

另一种方式:

文件test1.py:

print "test1.py"

文件service.py:

import subprocess

subprocess.call("test1.py", shell=True)

此方法的优点是您无需编辑现有 Python 脚本即可将其所有代码放入子例程中。

文档:Python 2Python 3

【讨论】:

  • 我必须使用subprocess.call("./test1.py", shell=True) 才能使其工作
  • 除非必要,否则不要使用shell=True
  • 它不会在当前目录不在 PATH 中的典型 Unix 上工作。 test1.py 应该是可执行的并且有 shebang 行 (#!/usr/bin/env python) 并且您应该指定完整路径或者您需要自己提供可执行文件:call([sys.executable, os.path.join(get_script_dir(), 'test1.py')]) where get_script_dir() is defined here
  • subprocess.call(['python', 'test1.py'])
  • @NitishKumarPal 没有;正如之前的 cmets 中已经指出的那样,您应该尽可能避免使用shell=True。这里没有 shell 功能,所以 subprocess.call(['python', 'test1.py']) 肯定更好,尽管您可能应该使用 check_callrun 代替(或者不将 Python 作为 Python 的子进程运行)。另见stackoverflow.com/questions/3172470/…
【解决方案4】:
import os

os.system("python myOtherScript.py arg1 arg2 arg3")  

使用 os 可以直接调用终端。如果您想更具体,可以将输入字符串与局部变量连接起来,即。

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)

【讨论】:

  • 应该避免调用os.system,你可以对来自Popen, Call, 的任何类做同样的事情
  • 来自Python documentation:子进程模块提供了更强大的工具来生成新进程并检索它们的结果;使用该模块优于使用此功能。
【解决方案5】:

这是subprocess 库的示例:

import subprocess

python_version = '3'
path_to_run = './'
py_name = '__main__.py'

# args = [f"python{python_version}", f"{path_to_run}{py_name}"]  # works in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]

res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

【讨论】:

  • 将 Python 作为 Python 的子进程运行几乎从来都不是正确的解决方案。如果您确实使用子流程,则应避免使用Popen,除非更高级别的功能确实无法满足您的要求。在这种情况下,check_callrun 可以满足您的所有需求,甚至更多,而您自己的代码中的管道大大减少。
【解决方案6】:

正如已经提到的,runpy 是从当前脚本运行其他脚本或模块的好方法。

顺便说一句,跟踪器或调试器执行此操作很常见,在这种情况下,直接导入文件或在子进程中运行文件等方法通常不起作用。

还需要注意使用exec来运行代码。您必须提供正确的run_globals 以避免导入错误或其他一些问题。详情请参考runpy._run_code

【讨论】:

    【解决方案7】:

    我发现runpy 标准库最方便。为什么?您必须考虑在test1.py 脚本中出现错误时的大小写,并且使用runpy 您可以在service.py 代码中处理此问题。回溯文本(在日志文件中写入错误以供将来调查)和错误对象(处理错误取决于其类型):当使用 subprocess 库时,我无法将错误对象从 test1.py 提升到 service.py ,只有回溯输出。 此外,与“将 test1.py 作为模块导入”解决方案相比,runpy 更好,因为您无需将test1.py 的代码包装到def main(): 函数中。

    以一段代码为例,用traceback模块捕捉最后一个错误文本:

    import traceback
    import runpy #https://www.tutorialspoint.com/locating-and-executing-python-modules-runpy
    
    from datetime import datetime
    
    
    try:
        runpy.run_path("./E4P_PPP_2.py")
    except Exception as e:
        print("Error occurred during execution at " + str(datetime.now().date()) + " {}".format(datetime.now().time()))
        print(traceback.format_exc())
        print(e)
    

    【讨论】:

      【解决方案8】:

      一个使用子流程的例子。

      from subprocess import run

      import sys

      run([sys.executable, 'fullpathofyourfile.py'])

      【讨论】:

        【解决方案9】:

        我更喜欢runpy

        #!/usr/bin/env python
        # coding: utf-8
        
        import runpy
        
        runpy.run_path(path_name='script-01.py')
        runpy.run_path(path_name='script-02.py')
        runpy.run_path(path_name='script-03.py')
        
        

        【讨论】:

          【解决方案10】:

          如果您希望 test1.py 保持可执行并具有与在 service.py 中调用它时相同的功能,请执行以下操作:

          test1.py

          def main():
              print "I am a test"
              print "see! I do nothing productive."
          
          if __name__ == "__main__":
              main()
          

          service.py

          import test1
          # lots of stuff here
          test1.main() # do whatever is in test1.py
          

          【讨论】:

          • 如果有运行时参数怎么办?
          • sys.argv 在这里仍然可以使用。您可以根据需要def main(*args)
          【解决方案11】:

          你不应该这样做。相反,这样做:

          test1.py:

           def print_test():
                print "I am a test"
                print "see! I do nothing productive."
          

          service.py

          #near the top
          from test1 import print_test
          #lots of stuff here
          print_test()
          

          【讨论】:

          • 当您导入 test1 时,它如何知道文件在哪里?它必须在同一个目录中吗?如果不是呢?
          【解决方案12】:

          将此添加到您的 python 脚本中。

          import os
          os.system("exec /path/to/another/script")
          

          这会像在 shell 中键入一样执行该命令。

          【讨论】:

            【解决方案13】:

            为什么不直接导入 test1?每个 python 脚本都是一个模块。更好的方法是拥有一个功能,例如main/run 在 test1.py 中,导入 test1 并运行 test1.main()。或者您可以将 test1.py 作为子进程执行。

            【讨论】:

            • 假设我使用import test1,因为我希望.py 下次编译为.pyc。如何将我的参数传递给它?我的 main() 函数会自动运行还是我必须在其中做一些特别的事情?
            【解决方案14】:

            这个过程有点不正统,但适用于所有 python 版本,

            假设你想在 'if' 条件下执行一个名为 'recommend.py' 的脚本,然后使用,

            if condition:
                   import recommend
            

            技术不同,但有效!

            【讨论】:

              【解决方案15】:

              第一次使用import test1 - 它将执行脚本。对于以后的调用,将脚本视为导入的模块,并调用reload(test1) 方法。

              reload(module)被执行时:

              • 重新编译 Python 模块的代码并重新执行 模块级代码,定义一组新的对象,这些对象绑定到模块字典中的名称。扩展模块的init函数没有被调用

              sys.modules 的简单检查可用于调用适当的操作。要继续将脚本名称引用为字符串 ('test1'),请使用 'import()' 内置函数。

              import sys
              if sys.modules.has_key['test1']:
                  reload(sys.modules['test1'])
              else:
                  __import__('test1')
              

              【讨论】:

              • reload 在 Python 3 中消失了。
              • 导入一个模块并不等同于运行它,例如,考虑if __name__ == "__main__":guard。可能还有其他更细微的差异。不要将任意代码留在全局级别。将它放在一个函数中并在导入后调用它,如accepted answer 中所建议的那样
              【解决方案16】:

              根据给定的示例,这是最好的方法:

              # test1.py
              
              def foo():
                  print("hellow")
              
              # test2.py
              from test1 import foo # might be different if in different folder.
              foo()
              

              但是根据标题,使用os.startfile("path") 是最好的方法,因为它很小且有效。这将执行指定的文件。我的python版本是3.x +。

              【讨论】:

                猜你喜欢
                • 2010-11-14
                • 1970-01-01
                • 2012-12-17
                • 1970-01-01
                • 2015-08-10
                • 1970-01-01
                • 1970-01-01
                • 2018-04-16
                • 2022-10-18
                相关资源
                最近更新 更多