从另一个脚本调用脚本的最佳方法是啥?
Posted
技术标签:
【中文标题】从另一个脚本调用脚本的最佳方法是啥?【英文标题】:What is the best way to call a script from another script?从另一个脚本调用脚本的最佳方法是什么? 【发布时间】:2010-11-14 06:43:52 【问题描述】:我有一个名为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 3: Call python script with input with in a python script using subprocess 还没有人发布runpy.run_module
答案?!
【参考方案1】:
一个使用子流程的例子。
from subprocess import run
import sys
run([sys.executable, 'fullpathofyourfile.py'])
【讨论】:
这对现有答案有什么好处?具体来说,Python3 应该使用call
,而不是run
【参考方案2】:
将此添加到您的 python 脚本中。
import os
os.system("exec /path/to/another/script")
这会像在 shell 中键入一样执行该命令。
【讨论】:
【参考方案3】:这个过程有点不正统,但适用于所有 python 版本,
假设你想在 'if' 条件下执行一个名为 'recommend.py' 的脚本,然后使用,
if condition:
import recommend
技术不同,但有效!
【讨论】:
【参考方案4】:这在 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 等价物的更全面处理:***.com/questions/436198/…
这不接受参数(要传递给 PY 文件)!【参考方案5】:
正如已经提到的,runpy
是从当前脚本运行其他脚本或模块的好方法。
顺便说一句,跟踪器或调试器执行此操作很常见,在这种情况下,直接导入文件或在子进程中运行文件等方法通常不起作用。
还需要注意使用exec
来运行代码。您必须提供正确的run_globals
以避免导入错误或其他一些问题。详情请参考runpy._run_code
。
【讨论】:
【参考方案6】:我更喜欢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')
【讨论】:
***.com/questions/67631/…【参考方案7】:这是subprocess
库的示例:
import subprocess
python_version = '3'
path_to_run = './'
py_name = '__main__.py'
# args = [f"pythonpython_version", f"path_to_runpy_name"] # Avaible 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_call
或 run
可以满足您的所有需求,甚至更多,而您自己的代码中的管道大大减少。
这正是我想要的。这不会等待其他脚本的执行。谢谢!【参考方案8】:
为什么不直接导入 test1?每个 python 脚本都是一个模块。更好的方法是拥有一个功能,例如在 test1.py 中 main/run,导入 test1 并运行 test1.main()。或者您可以将 test1.py 作为子进程执行。
【讨论】:
假设我使用import test1
,因为我希望.py
下次编译为.pyc
。如何将我的参数传递给它?我的 main() 函数会自动运行还是我必须在其中做一些特别的事情?【参考方案9】:
另一种方式:
文件test1.py:
print "test1.py"
文件service.py:
import subprocess
subprocess.call("test1.py", shell=True)
此方法的优点是您无需编辑现有 Python 脚本即可将其所有代码放入子例程中。
文档:Python 2、Python 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_call
或 run
代替(或者不将 Python 作为 Python 的子进程运行)。另见***.com/questions/3172470/…【参考方案10】:
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:子进程模块提供了更强大的工具来生成新进程并检索它们的结果;使用该模块优于使用此功能。【参考方案11】:
第一次使用import test1
- 它将执行脚本。对于以后的调用,将脚本视为导入的模块,并调用reload(test1)
方法。
当
重新编译 Python 模块的代码并重新执行 模块级代码,定义一组新的对象,这些对象绑定到模块字典中的名称。扩展模块的init函数没有被调用reload(module)
被执行时:
对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 中的建议在导入后调用它【参考方案12】:
执行此操作的通常方法如下所示。
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
位于某个遥远的目录怎么办?
@EvgeniSergeev 见***.com/questions/67631/…
但这并不能真正回答问题,是吗?您不是在执行整个脚本,而是在您导入的脚本中执行一些函数。
@GennaroTedesco:你错了。 service.py
中的 import test1
确实执行了 whole 脚本(它只定义了some_func()
,因为在这种情况下__name__ == '__main__'
将是False
)。这听起来像是所有 OP 想要做的。这个答案超出了这个范围,但确实回答了这个问题——然后是一些。
如果test1.py
不包含函数some_func()
的定义(而只是一些代码行,例如print("hello")
),那么您的代码将无法工作。在这个特定的示例中,它确实有效,因为您实际上是在导入一个外部函数,然后您会回调该函数。【参考方案13】:
如果您希望 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)
【参考方案14】:
你不应该这样做。相反,这样做:
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 时,它如何知道文件在哪里?它必须在同一个目录中吗?如果不是呢?以上是关于从另一个脚本调用脚本的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何调用 shell 脚本并从另一个 shell 脚本传递参数