我有一个名为
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
通常的方法如下所示。
test1.py
def some_func():
print 'in test 1, unproductive'
if __name__ == '__main__':
# test1.py executed as script
# do something
some_func()
服务.py
import test1
def service_func():
print 'service func'
if __name__ == '__main__':
# service.py executed as script
# do something
service_func()
test1.some_func()
这在 Python 2 中是可能的使用
execfile("test2.py")
如果对您的情况很重要,请参阅文档以了解名称空间的处理。
在 Python 3 中,这可以使用(感谢@fantastory)
exec(open("test2.py").read())
但是,您应该考虑使用不同的方法;你的想法(据我所知)看起来不太干净。
import os
os.system("python myOtherScript.py arg1 arg2 arg3")
使用 os 你可以直接调用你的终端。如果你想更具体,你可以将你的输入字符串与局部变量连接起来,即。
command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
如果您希望 test1.py 保持可执行状态,并具有与在 service.py 中调用时相同的功能,请执行以下操作:
test1.py
def main():
print "I am a test"
print "see! I do nothing productive."
if __name__ == "__main__":
main()
服务.py
import test1
# lots of stuff here
test1.main() # do whatever is in test1.py
我更喜欢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')
你不应该这样做。相反,做:
test1.py:
def print_test():
print "I am a test"
print "see! I do nothing productive."
服务.py
#near the top
from test1 import print_test
#lots of stuff here
print_test()
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')
正如已经提到的,
runpy
是从当前脚本运行其他脚本或模块的好方法。
顺便说一句,跟踪器或调试器这样做是很常见的,在这种情况下,直接导入文件或在子进程中运行文件等方法通常不起作用。
还需要注意使用
exec
来运行代码。您必须提供适当的run_globals
以避免导入错误或其他一些问题。详情请参阅runpy._run_code
为什么不直接导入 test1?每个 python 脚本都是一个模块。更好的方法是拥有一个功能,例如main/run in test1.py,导入test1并运行test1.main()。或者您可以将 test1.py 作为子进程执行。
我发现
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)
这个过程有点不正统,但适用于所有 python 版本,
假设您想在“if”条件下执行名为“recommend.py”的脚本,然后使用,
if condition:
import recommend
技术不同,但有效!
将此添加到您的 python 脚本中。
import os
os.system("exec /path/to/another/script")
这将执行该命令,就好像它是输入到 shell 中一样。
一个使用子流程的例子。
from subprocess import run
import sys
run([sys.executable, 'fullpathofyourfile.py'])
这是
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_)
根据给定的例子,这是最好的方法:
# 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 +.