从另一个Python脚本运行Python脚本,并传入参数

从另一个Python脚本运行Python脚本,并传入参数,python,Python,我想从另一个Python脚本运行一个Python脚本。我希望像使用命令行一样传递变量 例如,我将运行我的第一个脚本,该脚本将遍历一个值列表(0,1,2,3),并将这些值传递给第二个脚本script2.py 0,然后script2.py 1,等等 我发现这是一个类似的问题,但是ars的答案调用一个函数,当我想运行整个脚本时,不仅仅是一个函数,balpha的答案调用脚本,但没有参数。作为测试,我将其更改为如下内容: execfile("script2.py 1") 但它不能正确地接受变量。当我在s

我想从另一个Python脚本运行一个Python脚本。我希望像使用命令行一样传递变量

例如,我将运行我的第一个脚本,该脚本将遍历一个值列表(0,1,2,3),并将这些值传递给第二个脚本
script2.py 0
,然后
script2.py 1
,等等

我发现这是一个类似的问题,但是ars的答案调用一个函数,当我想运行整个脚本时,不仅仅是一个函数,balpha的答案调用脚本,但没有参数。作为测试,我将其更改为如下内容:

execfile("script2.py 1")
但它不能正确地接受变量。当我在script2.py中打印出
sys.argv
时,它是对第一个脚本“['C:\script1.py']的原始命令调用

我真的不想更改原始脚本(在我的示例中是script2.py),因为我不拥有它

我想一定有办法做到这一点;我只是不知道你是如何做到的。

尝试使用:

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

子流程模块:


有了它,您还可以重定向stdin、stdout和stderr。

这样做本质上是错误的。如果您从另一个Python脚本运行Python脚本,您应该通过Python而不是通过操作系统进行通信:

import script1
在理想情况下,您将能够直接调用
script1
中的函数:

for i in range(whatever):
    script1.some_function(i)
如有必要,您可以对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)

我认为这比将所有数据传递到操作系统和返回操作系统更可取;这太愚蠢了。

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

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


if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2], sys.argv[3])
换句话说,如果从命令行调用该模块,它将解析命令行选项,然后调用另一个函数
main()
,以执行实际工作。(实际参数会有所不同,解析可能会更复杂。)

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


os.system
可以工作,但这是一种迂回的(读“slow”)方式,因为您每次都在毫无理由地启动一个全新的Python解释器过程。

我认为良好的实践可能是这样的

import subprocess
subprocess.call(" python script2.py 1", shell=True)
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)
根据文件 子流程模块允许您生成新流程,连接到其输入/输出/错误管道,并获取其返回代码。此模块旨在替换几个旧模块和函数:

os.system
os.spawn*
os.popen*
popen2.*
commands.*
使用communicate()而不是.stdin.write、.stdout.read或.stderr.read,以避免由于任何其他操作系统管道缓冲区填满并阻塞子进程而导致死锁。

我认为通常最好使用
subprocess.Popen
而不是
os.system
:。是的,这就是
os.system
的帮助所说的。然而,对于简单的使用
os.system
是完成任务的最简单方法。当然,这取决于您的需要。您必须添加python才能运行脚本:os.system(“python script2.py 1”)@macdonjo:No,
os.system()
调用将等待您调用的内容完成后再继续。您可以使用
subprocess.Popen()
自己管理新的进程,或者使用
多处理
模块或其他各种解决方案。我遇到了问题
sh:1:*.py:not found
。添加python,然后它就会工作,即
os.system(“python script2.py 1”)
。可能是“错误的”“要做的事情,但如果您需要引用的脚本没有主脚本或函数,该怎么办…”。。。。导入将在导入时执行脚本,这可能不是您想要的(并且您不想重构它,因为人们也在按原样使用该脚本)。os/子流程可以处理这样的情况真的。。。但在我看来,这是另一个问题!对于多线程脚本来说,这不会失败吗?从更高层次的角度来看,将这种策略称为“错误”是“错误的”。当系统扩展时,对组件内部工作的详细了解就成了一个越来越大的问题——用Python编写的程序可能会用另一种语言重新设计,而使用操作系统的通用进程通信工具作为一种策略有很多好处。。。。那么依赖性呢?如果每个脚本都有自己的依赖项,为什么第一个脚本应该知道第二个脚本的所有依赖项?从架构的角度来看,错误的是在python中调用直接导入(IMHO)Re:“没有理由”。这不是错误。然而,有趣的是,看看不熟悉Futurama的人在随机堆栈溢出问题中“纠正”它需要多长时间:两年零三个月。:-)我嘲笑“没有葡萄干”只是因为它是一个可笑的打字错误,然后看到你的评论,在YouTube上找到了一个剪辑。更有趣的是,我有一个没有主脚本的脚本,但能够这样介绍:1。单独的函数def和独立语句2。在第3节“if name…”下进行参数解析。将def main(…)下的其余语句缩进,并使该逻辑对方法参数进行操作。然后我可以从另一个脚本(例如:单元测试)调用main方法。是的,Python真的使这种重构非常容易。我自己也做过不止一次类似的事情!如果主程序有可选参数,这种方法对我不起作用。这里我得到“列表索引超出范围”。最好有一个
Main(sys.argv)
并处理Main中的参数列表除非必要,否则不要使用
shell=True
。@Pi
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)
os.system
os.spawn*
os.popen*
popen2.*
commands.*