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

Jos*_*ton 277 python

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

例如:

文件test1.py

print "I am a test"
print "see! I do nothing productive."
Run Code Online (Sandbox Code Playgroud)

文件service.py

# Lots of stuff here
test1.py # do whatever is in test1.py
Run Code Online (Sandbox Code Playgroud)

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

ars*_*ars 259

通常的方法是执行此操作,如下所示.

test1.py

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

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

  • 如果`test1.py`位于某个远程目录中怎么办? (35认同)
  • 但这并没有真正回答这个问题,是吗?您没有执行整个脚本,而是从导入的脚本中执行某些功能. (11认同)
  • @GennaroTedesco:你错了。`service.py` 中的 `import test1` 确实执行了 **whole** 脚本(它只定义了 `some_func()`,因为在这种情况下 `__name__ == '__main__'` 将是 `False`)。这听起来像是所有 OP 想要做的。这个答案超出了这个范围,但确实回答了这个问题——然后是一些。 (5认同)
  • @EvgeniSergeev见http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path (3认同)
  • 如果说“ test1.py”不包含函数“ some_func()”的定义(而是仅包含一些代码行,例如“ print(“ hello”)`),那么您的代码将无法工作。在此特定示例中,它确实起作用,因为您实质上是在导入一个外部函数,然后再调用该外部函数。 (2认同)

bal*_*pha 127

这在Python 2中可以使用

execfile("test2.py")
Run Code Online (Sandbox Code Playgroud)

有关命名空间处理的文档,如果在您的情况下很重要,请参阅.

但是,您应该考虑使用不同的方法; 你的想法(从我所看到的)看起来不是很干净.

  • 直接我在python 32中需要的是exec(open('test2.py').read()) (8认同)
  • 此方法执行调用命名空间内的脚本.:) (7认同)
  • 要将命令行参数传递给脚本,您可以编辑`sys.argv`列表. (6认同)
  • 这不接受参数(将传递给PY文件)! (2认同)

小智 67

其他方式:

文件test1.py:

print "test1.py"
Run Code Online (Sandbox Code Playgroud)

文件service.py:

import subprocess

subprocess.call("test1.py", shell=True)
Run Code Online (Sandbox Code Playgroud)

此方法的优点是您不必编辑现有的Python脚本以将其所有代码放入子例程.

文档:Python 2,Python 3

  • 我不得不使用`subprocess.call("./ test1.py",shell = True)`来使它工作 (6认同)
  • 它不适用于当前目录不在PATH中的典型Unix.`test1.py`应该是可执行的并且有shebang行(`#!/ usr/bin/env python`)并且你应该指定完整路径或者你需要自己提供可执行文件:`call([sys.executable, os.path.join(get_script_dir(),'test1.py')])`其中[`get_script_dir()`在这里定义](http://stackoverflow.com/a/22881871/4279). (6认同)
  • 除非有必要,否则不要使用`shell = True`. (5认同)
  • @PiotrDobrogost - 你能指出哪些情况会使它变得必要吗? (2认同)
  • 只要正在运行的 shell 命令不是由用户输入形成的,`shell=True` 就可以。否则会有壳注入的风险。 (2认同)
  • 或`subprocess.call(['python','test1.py'])``。 (2认同)
  • @NitishKumarPal没有;正如前面的注释中已经指出的那样,您应该尽可能避免使用“ shell = True”。这里没有shell功能,所以`subprocess.call(['python','test1.py']))绝对更好,尽管您可能应该使用`check_call`或`run`来代替(或者不要将Python作为子进程运行) Python)。另请参阅/sf/ask/222072931/含义-of-shell-true-in-subprocess (2认同)

Mic*_*der 19

如果你希望test1.py保持可执行的功能与在service.py中调用它时的功能相同,那么执行以下操作:

test1.py

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

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

service.py

import test1
# lots of stuff here
test1.main() # do whatever is in test1.py
Run Code Online (Sandbox Code Playgroud)

  • 如果您有运行时参数怎么办? (2认同)

Fla*_*vio 13

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

Run Code Online (Sandbox Code Playgroud)


the*_*edz 12

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

test1.py:

 def print_test():
      print "I am a test"
      print "see! I do nothing productive."
Run Code Online (Sandbox Code Playgroud)

service.py

#near the top
from test1 import print_test
#lots of stuff here
print_test()
Run Code Online (Sandbox Code Playgroud)

  • 当您导入 test1 时,它如何知道文件在哪里?它必须在同一目录中吗?如果不是呢? (3认同)

gim*_*mel 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')
Run Code Online (Sandbox Code Playgroud)

  • `reload`在Python 3中消失了. (3认同)
  • 导入模块并不等同于运行它,例如,考虑`if __name__ == "__main__":` 守卫。可能还有其他更细微的差异。不要在全局级别留下任意代码。将其放入一个函数中,然后按照 [接受的答案](http://stackoverflow.com/a/1186847/4279) 中的建议在导入后调用它 (3认同)

小智 6

import os

os.system("python myOtherScript.py arg1 arg2 arg3")  
Run Code Online (Sandbox Code Playgroud)

使用操作系统,您可以直接拨打终端.如果您想要更具体,可以将输入字符串与局部变量连接起来,即.

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
Run Code Online (Sandbox Code Playgroud)

  • 来自 [Python 文档](https://docs.python.org/2/library/os.html#os.system): subprocess 模块提供了更强大的工具来生成新进程并检索其结果;使用该模块比使用此功能更好。 (4认同)

Cha*_*hen 5

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

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

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