从另一个脚本调用一个脚本的最佳方式是什么?

我有一个名为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

我知道有一种方法是打开文件,读取内容,然后对它求值。我想应该有更好的方法。至少我希望如此。

759087 次浏览

这可以在Python 2中使用

execfile("test2.py")

如果在您的情况中很重要,请参阅文档来了解名称空间的处理。

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

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

然而,你应该考虑使用不同的方法;(在我看来)你的想法不太清楚。

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

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

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()

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

执行reload(module)时:

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

可以使用sys.modules的简单检查来调用适当的操作。要继续以字符串('test1')的形式引用脚本名称,请使用内置的' <强> < / >强劲进口()”

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

如果你想让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

通常的做法是这样的。

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:

print "test1.py"

文件service.py:

import subprocess


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

这种方法的优点是,您不必编辑现有的Python脚本来将其所有代码放入子例程中。

文档:Python 2Python 3

import os


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

使用操作系统,您可以直接呼叫您的终端。如果你想更具体,你可以连接你的输入字符串与局部变量,即。

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

这是一个带有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_)

我更喜欢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')


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

顺便说一下,跟踪器或调试器通常会这样做,在这种情况下,直接导入文件或在子进程中运行文件等方法通常是行不通的。

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

这个过程有点非传统,但适用于所有的python版本,

假设你想在一个'if'条件中执行一个名为' recommendation .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'])

根据上面的例子,这是最好的方法:

# 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 +。

我发现runpy标准库最方便。为什么?你必须考虑在test1.py脚本中引发错误的情况,而使用runpy,你可以在service.py代码中处理这个问题。回溯文本(在日志文件中写入错误以供将来调查)和错误对象(处理错误取决于其类型):当使用subprocess库时,我无法将错误对象从test1.py提升到service.py,只能输出回溯。 此外,与“import test1.py as a module”相比;解决方案,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)