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


307

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

我知道一种方法是打开文件,读取内容并进行基本评估。我假设有一种更好的方法。或者至少我希望如此。


42
更好的方法是编写方法和类并使用它们
Aamir

相关文章:Python 3:使用子
进程

3
还没有人发布runpy.run_module答案吗?
阿兰·菲

Answers:


279

这样做的通常方法如下。

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

44
如果test1.py位于某个较远的目录中怎么办?
Evgeni Sergeev 2014年


18
但是,这并不能真正回答问题,对吗?您没有执行整个脚本,而是从导入的脚本中执行了一些功能。
gentl

2
@GennaroTedesco:你错了。将import test1service.py确实执行整个脚本(仅仅定义some_func(),因为__name__ == '__main__'False在这种情况下)。这听起来像OP想要做的所有事情。这个答案不仅限于此,但肯定会回答这个问题,然后再回答一些问题。
martineau

2
例如,如果test1.py不包含函数的定义some_func()(例如,仅包含几行代码print("hello")),则您的代码将无法工作。在此特定示例中,它确实起作用,因为您实质上是在导入一个外部函数,然后再调用该外部函数。
gentil '17

144

这可能在Python 2中使用

execfile("test2.py")

如果对您而言很重要,请参阅有关名称空间处理的文档

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

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

但是,您应该考虑使用其他方法。您的想法(据我所见)看起来不太干净。


9
直接在python 32中我需要的是exec(open('test2.py')。read())
fantastory 2012年

8
这种方法在调用名称空间内执行脚本。:)
dmvianna

6
要将命令行参数传递给脚本,可以编辑sys.argv列表。
jfs

1
关于Python 3当量的综合治疗:stackoverflow.com/questions/436198/...
约翰Ÿ

2
这不接受参数(将传递给PY文件)!
Apostolos

70

另一种方式:

文件test1.py:

print "test1.py"

文件service.py:

import subprocess

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

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

文档:Python 2Python 3


7
我不得不用subprocess.call("./test1.py", shell=True)它来使它起作用
asmaier 2013年

5
shell=True除非有必要,否则请勿使用。
Piotr Dobrogost

2
@PiotrDobrogost-您能指定哪种情况有必要吗?
sancho.s ReinstateMonicaCellio 2013年

7
它在当前目录不在PATH中的典型Unix上不起作用。test1.py应该是可执行文件,并带有shebang行(#!/usr/bin/env python),您应该指定完整路径,或者您需要自己提供可执行文件:call([sys.executable, os.path.join(get_script_dir(), 'test1.py')])get_script_dir()此处定义
jfs

5
或者subprocess.call(['python', 'test1.py'])
Big McLargeHuge

21

如果您希望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

3
如果您有运行时参数怎么办?
加百利博览会

13
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,
user1767754,2018年

Python文档中:子流程模块提供了更强大的工具,用于产生新流程并检索其结果;使用该模块优于使用此功能。
Big McLargeHuge

12

您不应该这样做。相反,请执行以下操作:

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

1
当您导入test1时,它如何知道文件在哪里?是否必须在同一目录中?如果没有呢?
NULL.Dude

8

使用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')

3
reload消失在Python 3
彼得·Dobrogost

1
导入模块并不等同于运行它,例如,请考虑if __name__ == "__main__":谨慎。可能还有其他更细微的差异。不要在全局级别上留下任意代码。把它放在一个功能和导入后把它作为建议接受的答案,而不是
JFS

5

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

3

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


3

如前所述,这runpy是从当前脚本运行其他脚本或模块的一种好方法。

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

还需要注意使用它exec来运行代码。您必须提供适当的信息run_globals以避免导入错误或其他问题。runpy._run_code有关详情,请参阅。


0

这是一个带subprocess库的示例:

import subprocess

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

# args = [f"python{python_version}", f"{path_to_run}{py_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_)

1
将Python作为Python的子进程运行几乎永远不是正确的解决方案。如果确实要使用子流程,则应避免使用,Popen除非高层功能确实不能满足您的要求。在这种情况下,check_call还是run会做你需要的一切多了,在自己的代码大大减少管道。
Tripleee

0

这个过程有些不合常规,但可以在所有python版本中使用,

假设您要在“ if”条件下执行名为“ recommend.py”的脚本,然后使用,

if condition:
       import recommend

技术不同,但是有效!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.