【问题标题】:Start background process in python via subprocess and write output to file通过子进程在python中启动后台进程并将输出写入文件
【发布时间】:2019-02-05 07:49:53
【问题描述】:

尊敬的 stackoverflow 用户,

我正在寻找一个可能非常简单的问题的解决方案。我想自动化一些量子化学计算,但遇到了一个小问题。

通常,您在远程服务器上使用您的输入文件 (*.inp) 作为后台进程来启动您的量子化学程序(在我的情况下称为 orca),并将输出通过管道传输到输出文件 (*.out) 中

nohup orca H2.inp >& H2.out &

或类似的东西。

现在我想使用 python 脚本(带有一些模板)来自动编写输入文件。最后,脚本应该以一种我可以在不停止 orca 的情况下注销服务器的方式开始计算。我试过了

subprocess.run(["orca", input_file], stdout=output_file)

但到目前为止它没有工作。如何使用子进程模块“模拟”顶部给出的命令?

问候

更新 我有一个名为H2.xyz 的文件。脚本读取并按点拆分文件名,并创建输入文件名H2.inp,输出应写入文件H2.out

更新 2 输入文件来源于*xyz文件通过

xyzfile = str(sys.argv[1])
input_file = xyzfile.split(".")[0] + ".inp"
output_file = xyzfile.split(".")[0] + ".out"

并通过模板在脚本中创建。最后我想通过以下方式运行脚本:

python3 script.py H2_0_1.xyz

【问题讨论】:

  • 试试subprocess.runshell = True
  • “如果通过 shell=True 显式调用 shell,应用程序有责任确保正确引用所有空格和元字符以避免 shell 注入漏洞”来自docs.python.org/3/library/…
  • output_file 文件的路径(我认为这行不通)或类似文件的对象(就像您使用 open(output_file, 'w') 方法得到的一样?
  • 到目前为止我还没有让它工作,所以我愿意接受任何解决方案。

标签: python subprocess


【解决方案1】:

为什么不简单:

subprocess.Popen(f'orca {input_file} >& {output_file}',
                 shell=True, stdin=None, stdout=None, stderr=None, close_fds=True)

更多信息: Run Process and Don't Wait

【讨论】:

  • 就像我在问题 shell=True 不安全中评论的那样,由于注入漏洞。在我的解决方案中,Python 正在处理这个问题。但是是的,我可能会杀了它xDDD
【解决方案2】:

对我来说(Windows,Python 2.7)call 方法工作得很好,如下所示:

with open('H2.out', 'a') as out :
    subprocess.call(['orca', infile], stdout=out,
                                      stderr=out,
                                      shell=True)   # Yes, I know. But It's Windows.

在 Linux 上,您可能不需要 shell=True 来获取参数列表。

【讨论】:

    【解决方案3】:

    子进程的使用重要吗?如果没有,您可以使用os.system

    在你的情况下,Python 调用会变得非常短

    os.system("nohup orca H2.inp >& H2.out &")
    

    应该可以解决问题。

    【讨论】:

      【解决方案4】:

      不久前我遇到了同样的问题。 这是我的解决方案:

      commandLineCode = "nohup orca H2.inp >& H2.out &"
      try:
          proc = subprocess.Popen(commandLineCode,
                                  stdin=subprocess.PIPE,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE,
                                  cwd = workingDir)
      
      except OSError:
          print("Windows Error occured")
          print(traceback.format_exc())
      
      timeoutInSeconds = 100
      try:
          outs, errs = proc.communicate(timeout = timeoutInSeconds)
      except subprocess.TimeoutExpired:
          print("timeout")
          proc.kill()
          outs, errs = proc.communicate()
      
      stdoutDecode = outs.decode("utf-8")
      stderrDecode = errs.decode("utf-8")
      
      for line in stdoutDecode.splitlines():
          # write line to outputFile
      if stderrDecode:
          for line in stderrDecode.splitlines():
              # write line to error log
      

      OSError 异常非常重要,因为您现在永远不会知道您的操作系统可能会做错什么。

      有关实际启动进程的communicate() 命令的更多信息,请阅读: https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate

      【讨论】:

        猜你喜欢
        • 2019-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多