2017-12-20 6 views
2

concurrent.futures을 사용하여 여러 텍스트 파일을 읽을 때 이상한 오류가 있음을 발견했습니다.파이썬 다중 처리 경쟁 조건

import os 
import concurrent.futures 

def read_file(file): 
    with open(os.path.join(data_dir, file),buffering=1000) as f: 
     for row in f: 
      try: 
       print(row) 
      except Exception as e: 
       print(str(e)) 

if __name__ == '__main__': 
    data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data')) 
    files = ['file1', 'file2'] 
    with concurrent.futures.ProcessPoolExecutor() as executor: 
     for file,_ in zip(files,executor.map(read_file,files)): 
      pass  

file1file2data 디렉토리에 임의의 텍스트 파일입니다 : 여기

작은 재현 예이다.

나는 다음과 같은 오류를 얻고있다 (이 할당되기 전에 기본적으로 프로세스가 data_dir 변수를 읽으려고) :

concurrent.futures.process._RemoteTraceback: 
""" 
Traceback (most recent call last): 
    File "C:\Users\my_username\AppData\Local\Continuum\Anaconda3\lib\concurrent\futures\process.py", line 175, in _process_worker 
    r = call_item.fn(*call_item.args, **call_item.kwargs) 
    File "C:\Users\my_username\AppData\Local\Continuum\Anaconda3\lib\concurrent\futures\process.py", line 153, in _process_chunk 
    return [fn(*args) for args in chunk] 
    File "C:\Users\my_username\AppData\Local\Continuum\Anaconda3\lib\concurrent\futures\process.py", line 153, in <listcomp> 
    return [fn(*args) for args in chunk] 
    File "C:\Users\my_username\Downloads\example.py", line 5, in read_file 
    with open(os.path.join(data_dir, file),buffering=1000) as f: 
NameError: name 'data_dir' is not defined 
""" 

The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
    File "example.py", line 16, in <module> 
    for file,_ in zip(files,executor.map(read_file,files)): 
    File "C:\Users\my_username\AppData\Local\Continuum\Anaconda3\lib\concurrent\futures\_base.py", line 556, in result_iterator 
    yield future.result() 
    File "C:\Users\my_username\AppData\Local\Continuum\Anaconda3\lib\concurrent\futures\_base.py", line 405, in result 
    return self.__get_result() 
    File "C:\Users\my_username\AppData\Local\Continuum\Anaconda3\lib\concurrent\futures\_base.py", line 357, in __get_result 
    raise self._exception 
NameError: name 'data_dir' is not defined 

내가 data_dir 할당 if __name__ == '__main__': 전에 블록을 배치 할 경우, 나는이 오류 및 얻지 않는다 코드가 예상대로 실행됩니다.

이 오류의 원인은 무엇입니까? 분명히 두 경우 모두 비동기 호출을 수행하기 전에 data_dir이 할당됩니다.

답변

3

fork(), 더 메모리는 공유되지 않습니다,하지만 파이썬은, 그 이유는 모듈 레벨 새로운 프로세스에 try to recreate 작업자 기능 환경의 뜻 변수가 작동합니다. doc for more detail을 참조하십시오.

+0

링크를 제공해 주셔서 감사합니다! 나는이 코드가 어제 Macbook에서 잘 돌아갔다는 것을 기억한다. 그래서 오늘이 오류를 Windows 컴퓨터에서 얻는 것은 꽤 혼란 스러웠다. –

+0

당신은 오신 것을 환영합니다! @MaxLawnboy 또한 파이썬에서'concurrent' lib가 있다는 것을 배웠습니다 .3. –

3

ProcessPoolExecutor은 새로운 파이썬 프로세스을 가져와 올바른 모듈을 가져오고 제공 한 함수를 호출합니다. data_dir모듈을 실행할 때 을 입력 할 때가 아니라을 입력하면 오류가 발생할 것으로 예상됩니다. 내가 프로세스가 부모의 파일 디스크립터를 상속 생각으로

, read_file 작업에 인수로 data_dir 파일 설명을 제공. 그래도 확인하셔야합니다.

그러나 ThreadPoolExecutor을 사용하려면 생성 된 스레드가 메모리를 공유하므로 예제가 작동해야합니다. 신선한 파이썬 인터프리터 프로세스를 시작하는 새로운 프로세스를 시작할 창을 볼 수 있습니다, 그래서 파이썬 사용 spawn하지

+0

'executor.map()'에서 사용하는 함수에 추가 인수를 전달할 수 없다고 생각합니다. Windows에서 작동하도록하는 유일한 방법은 모듈 수준에서'data_dir '을 정의하는 것입니다. –

+0

좋은 지적. 필자는 호출 된 함수를 수정하여 하나의 매개 변수로 튜플을 허용하고 실제로 map을 사용해야하는 경우 실제 인수를 팩에 넣을 수 있다고 생각합니다. – dorian