jpy*_*ams 4 python linux python-3.x python-asyncio
我正在编写一个包含 20,000 个任务的脚本,每个任务都会进行一个子进程调用和一个或两个 TCP 调用。为了使这不会花费一整天,我正在使用 Python 的新asyncio.
但是,我担心脚本运行时 Python 打印出的这些错误:
Exception ignored when trying to write to the signal wakeup fd:
BlockingIOError: [Errno 11] Resource temporarily unavailable
Run Code Online (Sandbox Code Playgroud)
它将打印一堆,但不会引发任何异常。我之前确实OSError了解Too many open files并断开了与服务器的连接,但是我使用信号量一次只允许与每个服务器建立 100 个连接,总共只有 700 个连接。
由于 Python 没有引发任何异常,因此我无法捕获错误。不过,这并不似乎影响脚本。
这些错误是我应该关注的吗? 如果是这样,我需要做什么才能摆脱它们?如果没有,我如何摆脱它们,使它们不在我的程序输出中?
另外,如果这些错误很严重,为什么 Python 会忽略它们而不是引发异常?
看起来限制因素是运行大量短命的subprocesses。来自Python 错误跟踪器:
“尝试写入信号唤醒 fd 时忽略异常”消息来自 Modules/signalmodule.c 中的信号处理程序。问题是 Python 获得了很多 SIGCHLD 信号(测试脚本每秒在我的计算机上创建 +300 个进程)。生产者(将信号编号写入“self”管道的信号处理程序)比消费者(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()
Run Code Online (Sandbox Code Playgroud)