是否可以在子进程中运行功能而无需线程化或编写单独的文件/脚本。


82
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

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


1
我相信您正在寻找多处理模块。
Noctis Skytower 2010年

Answers:


111

我认为您正在寻找更类似于多处理模块的内容:

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

子流程模块用于生成流程并使用其输入/输出执行操作-不适用于运行功能。

这是multiprocessing您的代码的版本:

from multiprocessing import Process, Queue

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

20
您可以将processify装饰器用作快捷方式:gist.github.com/2311116
schlamar

3
我假设这为子进程克隆了Python解释器及其所有环境?
詹斯

1
这是processify的一个分支,可在python 3中使用并支持生成器功能。 gist.github.com/stuaxo/889db016e51264581b50
Stuart Axon

4
请注意,此代码包含一个死锁,以防您要通过队列传递非平凡的大数据-在加入进程之前始终请先执行queue.get(),否则将挂起尝试写入队列的操作,而无需读取任何内容。
Petr Baudis

@schlamar我想在后台运行一个函数,但是我有一些资源限制,无法多次运行该函数,并且希望将该函数的额外执行排队。您对我该怎么做有任何想法吗?我在这里有我的问题。你能看看我的问题吗?任何帮助将是巨大的!
阿米尔(Amir)

17

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

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

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


我很好奇; 为什么要下票?我的答案有什么问题吗?
布莱恩·坎贝尔

多重处理不仅是fork()的高级包装,它还是一个多平台的多重处理工具箱(在Unix上使用fork)。这很重要,因为这意味着它可以在Windows上运行,而fork()则不能。编辑:这就是投票否决的原因,尽管我后来认为这可能不值得。不过,现在还为时已晚。Edit2:或更确切地说,在不跨平台时建议使用fork()就是原因。
Devin Jeanpierre 2010年

3
@Devin,如果需要的话,您随时可以收回您做过的一票。
亚历克斯·马丁里

编辑以澄清这一点。我明确提到这fork是不可移植的。通常,我会给出不可移植的答案以及不可移植的信息,然后让提问者决定是否足够。当我编辑完答案后,如果您认为我已经对它进行了充分的改进,那么您应该可以删除它。即使您没有,也不会感到难过,但我只是想检查一下自己弄错了什么。
布莱恩·坎贝尔

@Alex,不,你不能。经过一定时间后,您将无法恢复,直到进行编辑。在我重新考虑之前,已经过了这么长时间,因此“来不及”评论。无论如何,正如我所说,我认为这是不值得的,所以它不见了。我也很感谢并理解您的原因,但很高兴,无论哪种方式,您都不会感到难过。:p
Devin Jeanpierre 2010年

5

布赖恩·麦肯纳(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)功能立即使线程后台。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.