【问题标题】:Python subprocess.Popen : sys.stdout vs .txt file vs Cpickle.dumpPython subprocess.Popen:sys.stdout vs .txt 文件 vs Cpickle.dump
【发布时间】:2014-10-30 13:58:15
【问题描述】:

我想知道当您想从 python 脚本“返回”某些内容时,最佳做法是什么。

这是我的问题。我正在使用 subprocess.Popen 方法从 parentScript 运行 Python childScript。我想从第一个脚本的执行中得到一个包含两个浮点数的元组。

现在,我看到的第一种方法是在子进程函数中使用 sys.stdout 和管道,如下所示:

child.py:

if __name__ == '__main__':
   myTuple = (x,y)   
   sys.stdout.write(str(myTuple[0]) +":"+str(myTuple[1]))
   sys.stdout.flush()

父.py:

 p = subprocess.Popen([python, "child.py"], stdout=subprocess.PIPE)
 out, err = p.communicate()

虽然here 说在大多数情况下不推荐,但我不知道为什么...

第二种方法是将我的元组写入 Script1.py 中的文本文件并在 Script2.py 中打开它。但是我想写和读文件需要一些时间所以我不知道这是否是一个更好的方法?

最后,我可以使用 CPickle 并转储我的元组并从 script2.py 打开它。我想这会比使用文本文件快一点,但会比使用 sys.stdout 更好吗?

正确的做法是什么?

---------------------------------------编辑-------- ------------------------------------------

我忘了提到我不能使用 import,因为 parent.py 实际上会在文件夹中生成 child.py。事实上,我正在做一些多处理。

Parent.py 创建了 10 个目录,其中 child.py 被复制到每个目录中。然后我在几个处理器上运行来自 parent.py 的每个 child.py。我希望 parent.py 收集所有 child.py “返回”的结果。所以 parent.py 不能导入 child.py 因为它还没有生成,或者我可以做某种动态导入?我不知道...

---------------------------EDIT2-------- ------------------------------------------

另一个编辑回答关于我为什么要这样做的问题。 Child.py 实际上调用 ironpython 和另一个脚本来运行 .Net 程序集。我必须复制特定文件夹中的所有 child.py 文件的原因是因为该程序集生成了一个资源文件,然后由它自己使用。如果我不在每个子文件夹中复制 child.py (顺便说一下程序集),则资源文件将复制到根目录,这在我使用多处理模块调用多个进程时会产生冲突。如果您对这个整体架构有一些建议,我们非常欢迎:)。

谢谢

【问题讨论】:

  • 无关:一般来说,script1.pyscript2.pyfloat1float2 不是好名字。如果没有更具体的想法,您可以使用child.pyparent.py 作为脚本,使用numbersx, y 作为数字。
  • 好的,我现在正在编辑/补充它。谢谢!

标签: python subprocess popen sys


【解决方案1】:

普通,你应该使用import other_module,调用各种函数:

import other_module

x, y = other_module.some_function(param='z')

如果你可以运行脚本,你也可以导入它。

如果你想使用subprocess.Popen() 来传递几个浮点数,你可以使用 json 格式:它是人类可读的、精确的(在这种情况下)并且是机器可读的。例如:

child.py:

#!/usr/bin/env python
import json
import sys

numbers = 1.2345, 1e-20
json.dump(numbers, sys.stdout)

parent.py:

#!/usr/bin/env python
import json
import sys
from subprocess import check_output

output = check_output([sys.executable, 'child.py'])
x, y = json.loads(output.decode())

Child.py 实际上调用 ironpython 和另一个脚本来运行 .Net 程序集。我必须复制所有 child.py 文件的原因是因为该程序集生成了一个资源文件,然后由它使用。如果我不在每个子文件夹中复制 child.py ,则资源文件将复制到根目录,这会在我使用多处理模块调用多个进程时产生冲突。如果您对这个整体架构有一些建议,我们非常欢迎:)。

您可以将child.py中的代码放入parent.py并调用os.chdir()(在fork之后)在其自己的工作目录中执行每个multiprocessing.Process或使用cwd参数(它设置当前工作目录对于子进程)如果您使用 subprocess 模块运行程序集:

#!/usr/bin/env python
import os
import shutil
import tempfile
from multiprocessing import Pool

def init(topdir='.'):
    dir = tempfile.mkdtemp(dir=topdir) # parent is responsible for deleting it
    os.chdir(dir)

def child(n):
    return os.getcwd(), n*n

if __name__ == "__main__":
   pool = Pool(initializer=init)
   results = pool.map(child, [1,2,3])
   pool.close()
   pool.join()
   for dirname, _ in results:
       try:
           shutil.rmtree(dirname)
       except EnvironmentError:
           pass # ignore errors

【讨论】:

  • 我忘了提到我不能使用导入,因为 script2 实际上在文件夹中生成 script1。事实上,我正在做一些多处理。 Script2 创建了 10 个目录,其中每个目录都复制了 script1。然后我从 script2 运行每个 script1。我希望 script2 收集所有 script1 “返回”的结果。所以 script2 不能导入 script1 因为它还没有生成,或者我可以做某种动态导入?我不知道。但我会看看json。谢谢!
  • @user2390615: 1. 任何其他信息都应该放在您的问题中而不是评论中,以便其他人可以轻松找到它。 2. 如果脚本还没有生成,那么你也不能使用子进程运行它。 :) 如果文件已经存在,那么您可以导入它(将顶级代码移动到函数中,以避免在导入时执行它)。 3. 即时生成脚本并复制它们听起来不是一个好的设计——你应该更仔细地观察它。
  • @user2390615:我添加了架构建议。
  • 您是否应该(一次)将child.py 中的代码包含到上面的child() 函数中,即它应该是唯一的来源/没有复制等?
  • @Serge:我已经解决了权限问题(这是由于sticky bit on tmp directory,如果您使用其他任何东西,它就可以正常工作)。我已经更新了代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2019-06-28
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-19
相关资源
最近更新 更多