Я пишу сценарий, который составляет 20 000 задач, каждый из которых выполняет вызов подпроцесса и TCP-вызов или два. Чтобы сделать это не весь день, я использую новый asyncio
Python.
Тем не менее, меня беспокоят эти ошибки, которые Python выводит при запуске моего скрипта:
Exception ignored when trying to write to the signal wakeup fd:
BlockingIOError: [Errno 11] Resource temporarily unavailable
Он будет печатать кучу из них, но не создавать каких-либо исключений. Я получил OSError
о Too many open files
и ранее OSError
соединения с серверами, но я использовал семафоры, чтобы разрешить только 100 подключений к каждому серверу за один раз и всего 700 соединений.
Поскольку Python не создает никаких исключений, я не могу уловить ошибки. Но это не влияет на скрипт.
Являются ли эти ошибки чем-то, о чем я должен беспокоиться? Если да, что мне нужно сделать, чтобы избавиться от них? Если нет, как мне избавиться от них, чтобы они не были в моем программном выпуске?
Кроме того, если эти ошибки являются серьезными, почему Python игнорирует их, а не создает исключение?
Похоже, что лимитирующим фактором является работа с множеством недолговечных subprocess
. Из трекера Python:
"Исключение игнорируется при попытке записи в сигнал wakeup fd" происходит от обработчика сигнала в модулях /signalmodule.c. Проблема в том, что Python получает много сигналов SIGCHLD (тестовые скрипты создают +300 процессы в секунду на моем компьютере). Производитель (обработчик сигнала, записывающий номер сигнала в "сам"), быстрее, чем потребитель (обратный вызов BaseSelectorEventLoop._read_from_self).
С патчем я начинаю получать сообщения с 140 параллельными процессами, что намного лучше :-) IMO более 100 одновременных процессов сумасшедшие, не делайте этого дома :-) Я имею в виду процессы с очень коротким сроком службы. Предел - это количество SIGCHLD в секунду, поэтому количество процессов, которые заканчиваются на той же секунде.
Я изменил свой код, чтобы ограничить количество create_subprocess_exec
сразу. Я прекратил видеть ошибки, когда я опустился ниже 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()
The patch doesn't solve completly the issue.
Должен ли я подать отчет?
ulimit -a
мой лимит файлов равен 1024, и при многократном запускеls -l /proc/PID/fd | wc -l
, наибольшее количество открытых файлов, которое я получаю, составляет 692. Я не близок к максимальному количеству открытых файлов для системы