从另一个python脚本运行python脚本,传入args

Ger*_*ton 291 python

我想从另一个Python脚本运行Python脚本.我想传递变量,就像我使用命令行一样.

例如,我会跑我的,将通过值(0,1,2,3)的列表迭代第一个脚本,并通过那些到第二脚本script2.py 0,然后 script2.py 1,等

我找到了SO 1186789这是一个类似的问题但ars的答案调用了一个函数,因为我想运行整个脚本而不仅仅是一个函数,而balpha的答案调用脚本但没有args.我将其改为以下类似的测试:

execfile("script2.py 1")
Run Code Online (Sandbox Code Playgroud)

但它没有正确接受变量.当我打印出sys.argvscript2.py时,它是对第一个脚本"['C:\ script1.py']的原始命令调用.

我真的不想改变原始脚本(即我的例子中的script2.py),因为我不拥有它.

我认为必须有办法做到这一点,我很困惑你是怎么做到的.

Gre*_*ill 297

尝试使用os.system:

os.system("script2.py 1")
Run Code Online (Sandbox Code Playgroud)

execfile是不同的,因为它被设计为在当前执行上下文中运行一系列Python语句.这就是为什么sys.argv不为你改变的原因.

  • 我相信通常最好在`os.system`上使用`subprocess.Popen`:http://docs.python.org/library/subprocess.html#replacing-os-system. (46认同)
  • 你必须添加python来运行脚本:os.system("python script2.py 1") (19认同)
  • @macdonjo:不,`os.system()`调用等待,直到你调用的东西在继续之前完成.您可以使用`subprocess.Popen()`并自己管理新进程,或使用`multiprocessing`模块或其他各种解决方案. (11认同)
  • 是的,这就是对"os.system"的帮助.但是,对于简单的用途,`os.system`是完成工作的最简单方法.当然,这取决于你的需求. (9认同)
  • 我遇到了问题`sh:1:*.py:not found`.添加**python**然后它工作,即`os.system("python script2.py 1")`. (5认同)
  • 您还可以使用subprocess.check_call(). (2认同)
  • @SparkandShine:在原始问题中,`script2.py` 是可执行的。如果它不可执行,您将需要按照您说的去做。最好使用`sys.executable`,它是*当前* Python 可执行文件的名称(以防它与默认的不同)。所以类似:`os.system(sys.executable + " script2.py 1")` (2认同)

Kat*_*iel 100

这本身就是错误的做法.如果您从另一个Python脚本运行Python脚本,则应该通过Python而不是通过操作系统进行通信:

import script1
Run Code Online (Sandbox Code Playgroud)

在理想的世界中,您可以script1直接调用函数:

for i in range(whatever):
    script1.some_function(i)
Run Code Online (Sandbox Code Playgroud)

如果有必要,你可以破解sys.argv.使用上下文管理器有一种巧妙的方法可以确保您不进行任何永久性更改.

import contextlib
@contextlib.contextmanager
def redirect_argv(num):
    sys._argv = sys.argv[:]
    sys.argv=[str(num)]
    yield
    sys.argv = sys._argv

with redirect_argv(1):
    print(sys.argv)
Run Code Online (Sandbox Code Playgroud)

我认为这比将所有数据传递给操作系统更好; 那太傻了.

  • 这可能是"错误"的事情,但如果您需要引用的脚本没有主要或函数,那么导入将在导入时执行脚本,这可能不是您想要的(并且你不想重构它,因为人们也在使用那个脚本).os/subprocess可以处理这种情况 (12认同)
  • 多线程脚本不会失败吗? (4认同)
  • 从更高层次的角度来看,将这种策略称为"错误"是"错误的".当系统扩展时,对组件内部工作的详细了解会成为一个越来越大的问题 - 用Python编写的程序可能会用另一种语言重新设计,并且使用操作系统的通用流程通信工具可以提供很多功能.作为一种策略. (4认同)
  • ...那么依赖关系又如何呢?如果每个脚本都有自己的依赖项,为什么第一个脚本应该知道第二个脚本的所有依赖项?从架构的角度来看,错误的是在python中直接调用导入(恕我直言) (2认同)

kin*_*all 90

理想情况下,您要运行的Python脚本将使用接近结尾的代码进行设置:

def main(arg1, arg2, etc):
    # do whatever the script does


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2], sys.argv[3])
Run Code Online (Sandbox Code Playgroud)

换句话说,如果从命令行调用模块,它会解析命令行选项,然后调用另一个函数main()来执行实际工作.(实际的参数会有所不同,解析可能会更复杂.)

但是,如果你想从另一个Python脚本调用这样的脚本,你可以简单地直接import调用它modulename.main(),而不是通过操作系统.

os.system 将会工作,但它是环形交叉(读取"慢")的方式,因为你每次都没有葡萄干开始一个全新的Python解释程序.

  • 回复:"没有葡萄干." 这不是错误.然而,有趣的是看到不熟悉*Futurama*的人需要多长时间才能在随机Stack Overflow问题中"纠正"它:两年零三个月.:-) (12认同)
  • 近 5 年后我们再次来到这里,我很高兴看到你引用《飞出个未来》中弗莱困惑的大脑的话。 (2认同)

Chr*_*ams 41

子过程模块:http:
//docs.python.org/dev/library/subprocess.html#using-the-subprocess-module

import subprocess
subprocess.Popen("script2.py 1", shell=True)
Run Code Online (Sandbox Code Playgroud)

有了这个,你还可以重定向stdin,stdout和stderr.

  • 除非必要,否则不要使用`shell = True`. (10认同)

Med*_*hat 36

我认为好的做法可能是这样的;

import subprocess
cmd = 'python script.py'

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out, err = p.communicate() 
result = out.split('\n')
for lin in result:
    if not lin.startswith('#'):
        print(lin)
Run Code Online (Sandbox Code Playgroud)

根据文档子进程模块允许您生成新进程,连接到它们的输入/输出/错误管道,并获取它们的返回代码.该模块旨在替换几个较旧的模块和功能:

os.system
os.spawn*
os.popen*
popen2.*
commands.*
Run Code Online (Sandbox Code Playgroud)

使用communic()而不是.stdin.write,.stdout.read或.stderr.read来避免由于任何其他OS管道缓冲区填满和阻塞子进程而导致的死锁. 在这里阅读


小智 28

import subprocess
subprocess.call(" python script2.py 1", shell=True)
Run Code Online (Sandbox Code Playgroud)

  • 您可能希望扩展您的答案,以解释为什么这是比这里提供的其他一些答案更好的选择. (17认同)
  • 如何传递参数而不是字符串,例如列表?除了分别传递每个元素之外,还有其他选择吗? (2认同)
  • 除非必要,否则不要使用 shell=True。 (2认同)

归档时间:

查看次数:

690476 次

最近记录:

6 年,8 月 前