4

Я использую этот код, чтобы скоблить в API:рекурсии максимальная ошибка, когда при использовании futures.ProcessPoolExecutor но не futures.ThreadPoolExecutor с Praw обертка

submissions = get_submissions(1) 
with futures.ProcessPoolExecutor(max_workers=4) as executor: 
#or using this: with futures.ThreadPoolExecutor(max_workers=4) as executor: 
    for s in executor.map(map_func, submissions): 
     collection_front.update({"time_recorded":time_recorded}, {'$push':{"thread_list":s}}, upsert=True) 

Он отлично работает/быстро с потоками, но когда я пытаюсь использовать процессы я получаю полную очередь и эту ошибку:

File "/usr/local/lib/python3.4/dist-packages/praw/objects.py", line 82, in __getattr__ 
    if not self.has_fetched: 
RuntimeError: maximum recursion depth exceeded 
Exception in thread Thread-3: 
Traceback (most recent call last): 
    File "/usr/lib/python3.4/threading.py", line 920, in _bootstrap_inner 
    self.run() 
    File "/usr/lib/python3.4/threading.py", line 868, in run 
    self._target(*self._args, **self._kwargs) 
    File "/usr/lib/python3.4/concurrent/futures/process.py", line 251, in _queue_management_worker 
    shutdown_worker() 
    File "/usr/lib/python3.4/concurrent/futures/process.py", line 209, in shutdown_worker 
    call_queue.put_nowait(None) 
    File "/usr/lib/python3.4/multiprocessing/queues.py", line 131, in put_nowait 
    return self.put(obj, False) 
    File "/usr/lib/python3.4/multiprocessing/queues.py", line 82, in put 
    raise Full 
queue.Full 

Traceback (most recent call last): 
    File "reddit_proceses.py", line 64, in <module> 
    for s in executor.map(map_func, submissions): 
    File "/usr/lib/python3.4/concurrent/futures/_base.py", line 549, in result_iterator 
    yield future.result() 
    File "/usr/lib/python3.4/concurrent/futures/_base.py", line 402, in result 
    return self.__get_result() 
    File "/usr/lib/python3.4/concurrent/futures/_base.py", line 354, in __get_result 
    raise self._exception 
concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending. 

Следует отметить, что первоначально процессы работали большими и очень быстро для небольших извлечений данных, но теперь они не работают вообще. Является ли это ошибкой или что происходит с тем, что объект PRAW приведет к ошибке рекурсии с процессами, но не с потоками?

+0

Очередь, на которую он жалуется, представляет собой внутреннюю очередь, называемую 'call_queue'. Он определяется с максимальным размером: 'self._call_queue = multiprocessing.Queue (self._max_workers + EXTRA_QUEUED_CALLS)'. Он в процессе выключения «Исполнителя» при возникновении этой ошибки. Похоже, вы, возможно, отключили верхнюю часть первой трассировки. Можете ли вы включить это? Раньше я сталкивался с этой ошибкой 'queue.Full', но это было потому, что я взламывал' concurrent.futures.ProcessPoolExecutor' и менял его поведение/время выключения. Мне интересно, если бы вы попали в редкую ошибку. – dano

+0

@dano Я добавил более полную ошибку выше в исходном вопросе – sunny

+0

Хмм, Это похоже на возможный триггер: 'RuntimeError: превышена максимальная глубина рекурсии'. Кажется, это происходит из '/ usr/local/lib/python3.4/dist-packages/praw/objects.py'. Любые мысли по этому поводу? – dano

ответ

1

У меня была аналогичная проблема, перемещающаяся из потоков в процессы только я использовал executor.submit. Я думаю, что это может быть та же проблема, что и у вас, но я не могу быть уверен, потому что не знаю, в каком контексте работает ваш код.

В моем случае произошло следующее: я использовал свой код как скрипт, и я не использовал всегда рекомендованный if __name__ == "__main__":. Похоже, что при запуске нового процесса с исполнителем python загружает файл .py и запускает функцию, указанную в submit. Поскольку он загружает файл, код, который существует в основном файле (не внутри функций или выше, если предложение), запускается, поэтому каждый процесс запускает новый процесс с бесконечной рекурсией.

Похоже, что этого не происходит с потоками.

+0

Если я прав, у меня тоже была аналогичная проблема. В Windows все, что использует «многопроцессорность», должно иметь 'multiprocessing.freeze_support()' перед любым кодом, который не должен выполняться перед рабочей функцией в подпроцессах. Это связано с тем, что из-за отсутствия 'fork()' в Windows подпроцессы выполняются путем запуска той же командной строки с дополнительными аргументами. 'freeze_support()' ищет эти аргументы и запускает структуру 'multiprocessing' вместо следующего кода, если они присутствуют. –

+0

В моем случае 'multiprocessing.freeze_support()' не имеет значения. Может быть связано, но это не похоже на ту же проблему. Документация Python гласит, что freeze_support имеет эффект только в сценариях, замороженных в exe, созданных с помощью py2exe или аналогичных. Я тоже на Windows, но я не знаю, будет ли поведение на других os одинаковым или нет. – dyeray

+0

«Документация на Python говорит, что freeze_support имеет эффект только в сценариях, замороженных в exe» - да, это так, но это не так (по крайней мере, это не было, когда я последний раз разбирался с ним). –