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

433 投票
6 回答
1128632 浏览
提问于 2025-04-16 04:31

我想从一个Python脚本运行另一个Python脚本。我想像在命令行中那样传递变量。

比如,我会运行第一个脚本,它会遍历一个值的列表(0,1,2,3),然后把这些值传给第二个脚本,比如 script2.py 0,接着是 script2.py 1,依此类推。

我找到了一条在Stack Overflow上的问题1186789,这个问题和我想做的很相似,但里面的回答是调用一个函数,而我想运行整个脚本,而不仅仅是一个函数。还有一个回答是调用脚本,但没有传递参数。我把这个改成了下面这样的测试:

execfile("script2.py 1")

但是它没有正确接受变量。当我在script2.py中打印 sys.argv 时,它显示的是最初调用第一个脚本的命令 "['C:\script1.py']"。

我其实不想更改原来的脚本(也就是我例子中的script2.py),因为我并不拥有它。

我觉得一定有办法做到这一点,只是我不太明白该怎么做。

6 个回答

138

这样做本质上是错误的。如果你想从一个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)

我认为这样做比把所有数据传递给操作系统再返回要好,这样做实在是太傻了。

139

理想情况下,你想要运行的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脚本中调用这样的脚本,你可以直接import它,然后调用modulename.main(),这样就不需要通过操作系统来调用了。

使用os.system也是可以的,但这是一种比较绕的(可以理解为“慢”)方法,因为每次你都要启动一个全新的Python解释器进程,完全没有必要。

421

试试用 os.system 这个方法:

os.system("script2.py 1")

execfile 是不一样的,因为它是用来在当前的执行环境中运行一系列的Python语句。这就是为什么 sys.argv 对你来说没有变化的原因。

撰写回答