我正在使用Yelp中的(真棒)mrjob库在亚马逊的Elastic Map Reduce中运行我的python程序 . 它取决于标准python库中的子进程 . 从我的mac运行python2.7.2,一切都按预期工作
但是,当我在使用python2.7.2的Ubuntu LTS 11.04上使用完全相同的代码时,我遇到了一些奇怪的事情:
mrjob加载作业,然后尝试使用子进程与其子进程通信并生成此错误:
File "/usr/local/lib/python2.7/dist-packages/mrjob-0.3.1-py2.7.egg/mrjob/emr.py", line 1212, in _build_steps
steps = self._get_steps()
File "/usr/local/lib/python2.7/dist-packages/mrjob-0.3.1-py2.7.egg/mrjob/runner.py", line 1003, in _get_steps
stdout, stderr = steps_proc.communicate()
File "/usr/lib/python2.7/subprocess.py", line 754, in communicate
return self._communicate(input)
File "/usr/lib/python2.7/subprocess.py", line 1302, in _communicate
stdout, stderr = self._communicate_with_poll(input)
File "/usr/lib/python2.7/subprocess.py", line 1332, in _communicate_with_poll
poller = select.poll()
AttributeError: 'module' object has no attribute 'poll'
这似乎是子进程的问题,而不是mrjob .
我挖到/usr/lib/python2.7/subprocess.py并发现在导入期间运行:
if mswindows:
... snip ...
else:
import select
_has_poll = hasattr(select, 'poll')
通过编辑,我验证它确实设置了_has_poll == True . 这是正确的;在命令行上轻松验证 .
但是,当执行进展到使用Popen._communicate_with_poll时,选择模块已经改变了!这是通过在尝试使用select.poll()之前打印dir(select)生成的 .
['EPOLLERR', 'EPOLLET', 'EPOLLHUP', 'EPOLLIN', 'EPOLLMSG',
'EPOLLONESHOT', 'EPOLLOUT', 'EPOLLPRI', 'EPOLLRDBAND',
'EPOLLRDNORM', 'EPOLLWRBAND', 'EPOLLWRNORM', 'PIPE_BUF',
'POLLERR', 'POLLHUP', 'POLLIN', 'POLLMSG', 'POLLNVAL',
'POLLOUT', 'POLLPRI', 'POLLRDBAND', 'POLLRDNORM',
'POLLWRBAND', 'POLLWRNORM', '__doc__', '__name__',
'__package__', 'error', 'select']
没有名为'poll'的属性!?!?怎么消失了?
所以,我硬编码_has_poll = False,然后mrjob愉快地继续其工作,在AWS EMR中运行我的工作,子进程使用communic_with_select ...而且我坚持使用手工修改的标准库...
任何建议? :-)
2 回答
我有一个类似的问题,事实证明gevent用
gevent.select.select
取代了内置的select
模块,它没有poll
方法(因为它是一种阻塞方法) . 但由于某种原因,默认情况下gevent不会修补使用select.poll
的subprocess
.一个简单的解决方法是用
gevent.subprocess
替换subprocess
:如果在导入mrjob库之前执行此操作,它应该可以正常工作 .
很抱歉写一个完整的答案而不是评论,否则我会丢失代码缩进 .
我无法直接帮助你,因为某些内容似乎与你的代码紧密相关,但我可以通过依赖Python模块可以是任意对象的事实来帮助你找到,尝试类似的东西:
你将获得如下输出:
通过在代码中调用replaceSelect(),你应该能够获得有人删除poll()的回溯,这样你就可以理解为什么了 .
我希望我的FakeModule实现足够好,否则你可能需要修改它 .