Python多处理,PyAudio和wxPython [英] Python multiprocessing, PyAudio, and wxPython

查看:84
本文介绍了Python多处理,PyAudio和wxPython的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个wxPython GUI,并且想使用多重处理来创建一个单独的使用PyAudio的进程.也就是说,我想使用PyAudio,wxPython和多处理模块,但是尽管我可以使用其中任何两个,但不能同时使用这三个.具体来说,如果我从一个文件导入wx,并创建一个打开PyAudio的multiprocessing.Process,则PyAudio将不会打开.这是一个示例:

文件:A.py

import wx
import time
use_multiprocessing = True
if use_multiprocessing:
    from multiprocessing import Process as X
else:
    from threading import Thread as X
import B

if __name__=="__main__":
    p = X(target=B.worker)
    p.start()
    time.sleep(5.)
    p.join()

文件:B.py

import pyaudio

def worker():
    print "11"
    feed = pyaudio.PyAudio()
    print "22"
    feed.terminate()

在所有测试中,我都看到11打印,但是问题是我没有看到所示程序的22.

  • 如果我只注释掉import wx,我会看到22和pyaudio加载
  • 如果我仅设置use_multiprocessing=False,所以我改用线程,则会看到22和pyaudio负载.
  • 如果我在worker中执行其他操作,它将运行(仅pyaudio无法运行)

我已经在Python 2.6和2.7中进行了尝试; PyAudio 0.2.4、0.2.7和0.2.8;和wx 3.0.0.0和2.8.12.1;我正在使用OSX 10.9.4

解决方案

发生这种情况有两个原因,但它们看起来几乎相同.

无论哪种方式,根本问题是multiprocessing只是上下文和启动方法,以及问题#8713 作为背景.

但是您使用的是2.6,所以这对您没有帮助.那你该怎么办?


最简单的答案是从multiprocessing切换到第三方库 billiard . billiard是Python 2.7的multiprocessing的分支,它添加了Python 3.x和Celery的许多功能和错误修复.

我相信新版本具有与Python 3.4完全相同的修复程序,但我并不乐观(对不起,我没有安装它,并且无法在线找到文档……).

但是,我确定,它有一个相似但不同的解决方案,继承自Celery:在调用库中的任何其他内容之前,先调用billiards.forking_enable(False). (或者,从程序外部,设置环境变量MULTIPROCESSING_FORKING_DISABLE=1.)


*通常,CF可以检测到问题并调用__THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YO‌U_MUST_EXEC__,这会记录一条错误消息并失败.但是有时它不能,并且将等待最终永远等待任何人都无法发送的事件.谷歌搜索该字符串以获取更多信息.

**有关线程Tkinter等效问题的详细信息,请参见#5527 .潜在的问题.这会影响所有类似BSD的* nix,而不仅仅是OS X.

I have a wxPython GUI, and would like to use multiprocessing to create a separate process which uses PyAudio. That is, I want to use PyAudio, wxPython, and the multiprocessing module, but although I can use any two of these, I can't use all three together. Specifically, if from one file I import wx, and create a multiprocessing.Process which opens PyAudio, PyAudio won't open. Here's an example:

file: A.py

import wx
import time
use_multiprocessing = True
if use_multiprocessing:
    from multiprocessing import Process as X
else:
    from threading import Thread as X
import B

if __name__=="__main__":
    p = X(target=B.worker)
    p.start()
    time.sleep(5.)
    p.join()

file: B.py

import pyaudio

def worker():
    print "11"
    feed = pyaudio.PyAudio()
    print "22"
    feed.terminate()

In all my tests I see 11 print, but the problem is that I don't see 22 for the program as shown.

  • If I only comment out import wx I see 22 and pyaudio loads
  • If I only set use_multiprocessing=False so I use threading instead, I see 22 and pyaudio loads.
  • If I do something else in worker, it will run (only pyaudio doesn't run)

I've tried this with Python 2.6 and 2.7; PyAudio 0.2.4, 0.2.7, and 0.2.8; and wx 3.0.0.0 and 2.8.12.1; and I'm using OSX 10.9.4

解决方案

There are two reasons this can happen, but they look pretty much the same.

Either way, the root problem is that multiprocessing is just forking a child. This could be either causing CoreFoundation to get confused about its runloop*, or causing some internal objects inside wx to get confused about its threads.**


But you don't care why your child process is deadlocking; you want to know how to fix it.

The simple solution is to, instead of trying to fork and then clean up all the stuff that shouldn't be copied, spawn a brand-new Python process and then copy over all the stuff that should.

As of Python 3.4, there are actually two variations on this. See Contexts and start methods for details, and issue #8713 for the background.

But you're on 2.6, so that doesn't help you. So, what can you do?


The easiest answer is to switch from multiprocessing to the third-party library billiard. billiard is a fork of Python 2.7's multiprocessing, which adds many of the features and bug fixes from both Python 3.x and Celery.

I believe new versions have the exact same fix as Python 3.4, but I'm not positive (sorry, I don't have it installed, and can't find the docs online…).

But I'm sure that it has a similar but different solution, inherited from Celery: call billiards.forking_enable(False) before calling anything else on the library. (Or, from outside the program, set the environment variable MULTIPROCESSING_FORKING_DISABLE=1.)


* Usually, CF can detect the problem and call __THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY___YO‌U_MUST_EXEC__, which logs an error message and fails. But sometimes it can't, and will wait end up waiting forever for an event that nobody can send. Google that string for more information.

** See #5527 for details on the equivalent issue with threaded Tkinter, and the underlying problem. This one affects all BSD-like *nixes, not just OS X.

这篇关于Python多处理,PyAudio和wxPython的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆