【问题标题】:Is it possible to run function in a subprocess without threading or writing a separate file/script.是否可以在子进程中运行函数而无需线程或编写单独的文件/脚本。
【发布时间】:2011-01-04 00:48:03
【问题描述】:
import subprocess

def my_function(x):
    return x + 100

output = subprocess.Popen(my_function, 1) #I would like to pass the function object and its arguments
print output 
#desired output: 101

我只找到了有关使用单独脚本打开子进程的文档。有谁知道如何传递函数对象,甚至是传递函数代码的简单方法?

【问题讨论】:

标签: python function subprocess popen python-multiprocessing


【解决方案1】:

我认为您正在寻找更像多处理模块的东西:

http://docs.python.org/library/multiprocessing.html#the-process-class

子进程模块用于生成进程并使用它们的输入/输出执行操作 - 不用于运行函数。

这是您的代码的multiprocessing 版本:

from multiprocessing import Process, Queue

# must be a global function    
def my_function(q, x):
    q.put(x + 100)

if __name__ == '__main__':
    queue = Queue()
    p = Process(target=my_function, args=(queue, 1))
    p.start()
    p.join() # this blocks until the process terminates
    result = queue.get()
    print result

【讨论】:

  • 您可以使用processify 装饰器作为快捷方式:gist.github.com/2311116
  • 我假设这会为子进程克隆 Python 解释器及其所有环境?
  • 这是一个在 python 3 中工作并支持生成器函数的 processify 的分支。 gist.github.com/stuaxo/889db016e51264581b50
  • 请注意,此代码包含死锁,以防您通过队列传递非平凡的大数据 - 始终在加入进程之前 queue.get() ,否则它将挂起尝试写入队列没有读取它。
  • @schlamar 我想在后台运行一个函数,但我有一些资源限制,无法按我想要的次数运行该函数,并且想要将函数的额外执行排队。你知道我应该怎么做吗?我有我的问题here。你能看看我的问题吗?任何帮助都会很棒!
【解决方案2】:

您可以使用标准的 Unix fork 系统调用,如 os.fork()fork() 将创建一个新进程,运行相同的脚本。在新进程中返回0,而在旧进程中返回新进程的进程ID。

child_pid = os.fork()
if child_pid == 0:
  print "New proc"
else:
  print "Old proc"

对于更高级别的库,它提供多处理支持,为使用多个进程提供可移植的抽象,有multiprocessing 模块。 IBM DeveloperWorks 上有一篇文章Multiprocessing with Python,简要介绍了这两种技术。

【讨论】:

  • 我很好奇;为什么投反对票?我的回答有什么问题吗?
  • Multiprocessing 不仅仅是 fork() 的更高级别的包装器,它还是一个多平台多处理工具包(在 unix 上使用 fork)。这很重要,因为这意味着它可以在 Windows 上运行,而 fork() 则不能。编辑:这就是投反对票的原因,尽管我后来认为这可能不值得。不过,要收回来已经太晚了。编辑2:或者更确切地说,当它不是跨平台时建议使用 fork() 是原因。
  • @Devin,如果你愿意,你可以随时收回你投的反对票。
  • 然后进行了编辑以澄清这一点。我明确提到fork 不可移植;我通常会给出不可携带的答案以及它们不可携带的信息,并让提问者决定这对他们来说是否足够。正如我已经编辑了我的答案,如果你觉得我已经充分改进了它,你应该能够删除反对票;虽然如果你不这样做也没有什么不好的感觉,我只是想检查一下我做错了什么。
  • @Alex,不,你不能。经过一定时间后,您无法将其收回,直到发生编辑。在我重新考虑之前已经过了这么长时间,因此“为时已晚”的评论。无论如何,正如我所说,我认为它不值得,所以它消失了。我也很欣赏和理解你的理由,我很高兴无论哪种方式都不会感到难过。 :p
【解决方案3】:

Brian McKenna 上面关于多处理的帖子确实很有帮助,但如果您想走线程路线(与基于进程相反),这个示例将帮助您入门:

import threading
import time

def blocker():
    while True:
        print "Oh, sorry, am I in the way?"
        time.sleep(1)

t = threading.Thread(name='child procs', target=blocker)
t.start()

# Prove that we passed through the blocking call
print "No, that's okay" 

您还可以使用setDaemon(True) 功能立即将线程置于后台。

【讨论】:

  • 请注意,由于 GIL,Python 中的线程仅对等待事物(即非 CPU 绑定任务)真正有用。对于 CPU 密集型任务,必须使用多处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多