如何使用python子进程模块执行包含脚本的字符串

时间:2015-05-19 17:51:06

标签: python shell subprocess

我在字符串中收到一个脚本,试图找到一种使用python的子进程模块执行它的方法。 e.g。

import subprocess
script = """#!/usr/bin/python
            print "inside script"
         """
subprocess.Popen(script)

这引发了一个OSError:说没有这样的文件或目录,这是公平的,因为我认为它试图寻找命令名。

然后我尝试subprocess.Popen(script, shell=True)仅适用于shell命令并完全忽略#!在脚本的顶部。有没有办法让suprocess运行我的脚本存储在字符串中,就像它的可执行文件一样?

4 个答案:

答案 0 :(得分:2)

正如您可以在Popen Python Documentation中读到Popen的参数是要启动的可执行文件,而不是要执行的某些脚本的内容。您不能以这种方式使用Popen

如果您真的想要,可以将脚本写入文件,然后将该文件名传递给Popen,但对于您遇到的任何问题,这似乎都不是一个优雅的解决方案。

看到你想要的只是从字符串中执行一些Python代码,你将要使用exec builtin function

答案 1 :(得分:2)

此解决方案基于-c(编译)Python解释器cmdline参数。它完全忽略了使用shell属性。

Popen可能以类似的方式创建。 subprocess.call用于表示脚本实际上已执行,并且python解释器返回代码由执行的代码更改。

import subprocess

executable_code = """
print 'inside script'
print 123
"""

code_with_exception = """
raise Exception()
"""

ok_rc = subprocess.call(['python', '-c', executable_code])
assert ok_rc == 0

bad_rc = subprocess.call(['python', '-c', code_with_exception])
assert bad_rc == 1

其他改进是跳过'python'硬编码字符串并使用sys.executable

  

一个字符串,给出Python解释器的可执行二进制文件的绝对路径,在有意义的系统上。如果Python是   无法检索其可执行文件的真实路径,sys.executable   将是一个空字符串或无。

import sys
import subprocesss
code = "raise Exception()"
bad_rc = subprocess.call([sys.executable, '-c', code])
assert bad_rc == 1

答案 2 :(得分:1)

您可以通过将脚本转换为子python的stdin来运行脚本。这可能是较大脚本的首选解决方案:

import sys
import subprocess as subp
import shutil

script = """\
import sys
print "hello", sys.argv
"""

p = subp.Popen([sys.executable, '-', 'arg1', 'arg2'], stdin=subp.PIPE)
p.stdin.write(script)
p.stdin.close()
p.wait()

我在ssh个连接中使用此技巧来控制远程服务器。

答案 3 :(得分:1)

使用subprocess模块执行字符串作为Python脚本:

>>> import subprocess, sys, textwrap
>>> subprocess.call(textwrap.dedent('''
...    print "Hello, world!"
... '''), shell=True, executable=sys.executable)
Hello, world!
0

虽然@wich suggestedPython builtin function exec(),但您可以使用multiprocessing - 它是关于Python 2的声明:

>>> exec 'print "Hello, exec!"'
Hello, exec!

如果您想在其他流程中运行Python代码,可以使用concurrent.futures modulesHibernate Communications Link Failure in Hibernate Based Java Servlet application powered by MySQL

#!/urs/bin/env python2
from multiprocessing import Process, freeze_support

def run(code):
    exec code # Python 2

if __name__ == "__main__":
    freeze_support()
    Process(target=run, args=['print "Hello, multiprocessing"']).start()