【问题标题】:How to execute a string containing a script using python subprocess module如何使用python子进程模块执行包含脚本的字符串
【发布时间】:2015-05-19 17:51:05
【问题描述】:

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

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

这会引发 OSError: say there is no such file or directory,这很公平,因为我认为它试图查找命令名称。

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

【问题讨论】:

  • 将字符串保存到文件中,然后执行实际的脚本?
  • 是的,这是我最后的选择。希望我可能错过了一些东西,并且有一些其他的子流程魔法可以实现这一点。
  • 你想达到什么目的?
  • 我正在尝试模拟一些外部流程进行测试。有人可以将字符串中的脚本传递给我的模拟函数,我可以执行该字符串而不是实际过程。例如有人可以说 mock git as sleep(60)。

标签: python shell subprocess


【解决方案1】:

此解决方案基于-c(编译)Python 解释器命令行参数。它完全忽略了使用 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】:

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

    如果您真的愿意,可以将脚本写入文件,然后将该文件名传递给 Popen,但这似乎不是解决您的问题的优雅解决方案。

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

    【讨论】:

      【解决方案3】:

      您可以通过将脚本泵入子 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 连接中使用这个技巧来控制远程服务器。

      【讨论】:

      • 你可以用p.communicate(script)代替最后3行。
      • @J.F.Sebastian 是绝对正确的。重要的是管道已关闭,python 将其视为 EOF 并执行脚本。
      【解决方案4】:

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

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

      虽然@wich suggested 你可以使用Python builtin function exec() -- 这是 Python 2 上的声明:

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

      如果您想在不同的进程中运行 Python 代码,可以使用 multiprocessingconcurrent.futures modules

      #!/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()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-30
        • 2010-10-16
        • 2013-11-02
        • 2013-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多