我正在编写一个20,000个任务的脚本,每个任务进行一次子进程调用和一个或两个TCP调用。为了使这不是一整天,我使用Python的新asyncio
。
但是,我担心Python脚本运行时打印出的这些错误:
Exception ignored when trying to write to the signal wakeup fd:
BlockingIOError: [Errno 11] Resource temporarily unavailable
它将打印出一堆,但不会引发任何异常。我确实得到了关于OSError
的Too many open files
s并且之前断开了与服务器的连接,但我使用信号量一次只允许100个连接到每个服务器,总共只有700个连接。
由于Python没有引发任何异常,我无法发现错误。但它似乎并没有影响脚本。
这些错误是我应该关注的吗?如果是这样,我需要做些什么才能摆脱它们?如果没有,我如何摆脱他们,因为他们不在我的程序的输出?
另外,如果这些错误很严重,为什么Python会忽略它们而不是引发异常呢?
看起来限制因素是运行大量短命的subprocess
es。来自Python bug tracker:
“尝试写入信号唤醒fd时忽略异常”消息来自Modules / signalmodule.c中的信号处理程序。问题是Python获取了很多SIGCHLD信号(测试脚本在我的计算机上每秒创建+300个进程)。生产者(将信号编号写入“自”管道的信号处理程序)比消费者(BaseSelectorEventLoop._read_from_self回调)更快。
有了补丁,我开始收到140个并发进程的消息,这要好得多:-) IMO超过100个并发进程是疯了,不要在家里这样做:-)我的意思是生命周期很短的进程。限制是每秒SIGCHLD的数量,因此进程数量以相同的秒数结束。
我改变了我的代码以限制一次运行多少个create_subprocess_exec
es。当我低于35时,我停止看到错误,但我可能会将它设置为20只是为了确定。你的旅费可能会改变。
async def myTask(stuff, semaphore, loop):
with semaphore:
process = await asyncio.create_subprocess_exec('short_program', loop=loop)
def taskRunner(stuffs):
loop = asyncio.get_event_loop()
semaphore = asyncio.Semaphore(20) # limit how many can run at a time
tasks = [
asyncio.ensure_future(myTask(semaphore, loop))
for i in range(20000)
]
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()