[python] 파이썬으로 거대한 CSV 처리가 갑자기 멈출 때 ‘killed’는 무엇을 의미합니까?

큰 CSV 파일을 가져온 다음 파일에서 각 단어의 발생 횟수를 계산 한 다음 다른 CSV 파일로 내보내는 Python 스크립트가 있습니다.

그러나 일어나는 일은 일단 계산 부분이 완료되고 내보내기가 시작 Killed되면 터미널에 말합니다 .

나는 이것이 메모리 문제라고 생각하지 않습니다 (만약 내가 메모리 오류가 아니라고 가정한다면 Killed).

프로세스가 너무 오래 걸릴 수 있습니까? 그렇다면 제한 시간을 연장하여 이것을 피할 수 있습니까?

다음은 코드입니다.

csv.field_size_limit(sys.maxsize)
    counter={}
    with open("/home/alex/Documents/version2/cooccur_list.csv",'rb') as file_name:
        reader=csv.reader(file_name)
        for row in reader:
            if len(row)>1:
                pair=row[0]+' '+row[1]
                if pair in counter:
                    counter[pair]+=1
                else:
                    counter[pair]=1
    print 'finished counting'
    writer = csv.writer(open('/home/alex/Documents/version2/dict.csv', 'wb'))
    for key, value in counter.items():
        writer.writerow([key, value])

그리고 인쇄 Killed후 발생 finished counting하며 전체 메시지는 다음과 같습니다.

killed (program exited with code: 137)



답변

종료 코드 137 (128 + 9)은 신호 9를 수신하여 프로그램이 종료되었음을 나타냅니다 SIGKILL. 이것은 또한 killed메시지를 설명합니다 . 문제는 왜 그 신호를 받았습니까?

가장 가능성이 높은 이유는 아마도 프로세스가 사용할 수있는 시스템 리소스 양의 일부 제한을 초과했기 때문일 것입니다. OS 및 구성에 따라 열린 파일이 너무 많거나 파일 시스템 공간을 너무 많이 사용했거나 다른 것을 사용할 수 있습니다. 프로그램이 너무 많은 메모리를 사용하고있을 가능성이 가장 높습니다. 메모리 할당이 실패하기 시작했을 때 문제가 발생할 위험이있는 대신 시스템은 너무 많은 메모리를 사용하는 프로세스에 종료 신호를 보냈습니다.

앞서 언급했듯이 인쇄 후 메모리 제한에 도달 할 수있는 한 가지 이유 finished countingcounter.items()최종 루프에서에 대한 호출이 사전의 모든 키와 값을 포함하는 목록을 할당하기 때문입니다. 사전에 많은 양의 데이터가있는 경우 이는 매우 큰 목록 일 수 있습니다. 가능한 해결책은 counter.iteritems()발전기 를 사용 하는 것입니다. 목록의 모든 항목을 반환하는 대신 훨씬 적은 메모리 사용으로 항목을 반복 할 수 있습니다.

따라서 최종 루프로 이것을 시도하는 것이 좋습니다.

for key, value in counter.iteritems():
    writer.writerow([key, value])

Python 3에서는 itemsPython 2 버전과 동일한 오버 헤드가없는 “dictionary view”객체를 반환합니다. 을 대체 iteritems하므로 나중에 Python 버전을 업그레이드하면 루프를 원래대로 다시 변경하게됩니다.


답변

관련된 두 가지 저장 영역이 있습니다 : 스택과 힙. 스택은 메서드 호출의 현재 상태 (예 : 로컬 변수 및 참조)가 보관되는 곳이고 힙은 객체가 저장되는 곳입니다. 재귀와 기억

counter힙 영역의 메모리를 너무 많이 소비 하는 딕셔너리 에 너무 많은 키가 있다고 생각하므로 Python 런타임은 OutOfMemory 예외를 발생시킵니다.

저장하려면 카운터 와 같은 거대한 물체를 만들지 마십시오. .

1. 스택 오버플로

너무 많은 지역 변수를 생성하는 프로그램.

Python 2.7.9 (default, Mar  1 2015, 12:57:24)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> f = open('stack_overflow.py','w')
>>> f.write('def foo():\n')
>>> for x in xrange(10000000):
...   f.write('\tx%d = %d\n' % (x, x))
... 
>>> f.write('foo()')
>>> f.close()
>>> execfile('stack_overflow.py')
Killed

2.OutOfMemory

거인을 만드는 프로그램 dict에는 너무 많은 키가 포함되어 있습니다.

>>> f = open('out_of_memory.py','w')
>>> f.write('def foo():\n')
>>> f.write('\tcounter = {}\n')
>>> for x in xrange(10000000):
...   f.write('counter[%d] = %d\n' % (x, x))
... 
>>> f.write('foo()\n')
>>> f.close()
>>> execfile('out_of_memory.py')
Killed

참고 문헌


답변

시간이 오래 걸린다는 이유만으로 프로세스를 죽이는 것은 의심 스럽습니다. Killed는 일반적으로 외부에서 프로세스가 종료되었음을 의미하지만이 경우 Ctrl-C를 누르면 Python이 KeyboardInterrupt 예외로 종료되기 때문에이 경우는 아닐 것입니다. 또한 Python에서 문제가 발생하면 MemoryError 예외가 발생합니다. 일어날 수있는 일은 Python 또는 표준 라이브러리 코드에서 버그가 발생하여 프로세스 충돌을 유발하는 것입니다.


답변

아마도 메모리가 부족하여 커널이 프로세스를 종료했습니다.

OOM Killer 에 대해 들어 보셨습니까 ?

다음은 CSV 파일의 방대한 데이터 집합을 처리하기 위해 개발 한 스크립트의 로그입니다.

Mar 12 18:20:38 server.com kernel: [63802.396693] Out of memory: Kill process 12216 (python3) score 915 or sacrifice child
Mar 12 18:20:38 server.com kernel: [63802.402542] Killed process 12216 (python3) total-vm:9695784kB, anon-rss:7623168kB, file-rss:4kB, shmem-rss:0kB
Mar 12 18:20:38 server.com kernel: [63803.002121] oom_reaper: reaped process 12216 (python3), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB

에서 가져 왔습니다 /var/log/syslog.

원래:

PID 12216이 피해자 로 선출 되었으므로 (총 VM의 + 9Gb 사용으로 인해) oom_killer가이를 거두었습니다.

다음은 OOM 동작 에 대한 기사 입니다.


답변

VirtualBox새로운 Ubuntu 20.04 LTS 의 공유 폴더에서 Python 스크립트를 실행하려고 할 때도 똑같은 일이 발생했습니다 . Killed내 개인 라이브러리를로드 하는 동안 Python이 구제되었습니다 . 폴더를 로컬 디렉토리로 옮겼을 때 문제가 사라졌습니다. 그것은 나타납니다Killed폴더를 이동 한 후 누락 된 라이브러리 메시지를 받았기 때문에 라이브러리의 초기 가져 오기 중에 중지 된 .

컴퓨터를 다시 시작한 후 문제가 사라졌습니다.

따라서 사람들은 어떤 종류의 공유를 통해 프로그램을 로컬 디렉토리로 옮기거나 OS를 재부팅해야하는 일시적인 문제 일 수 있습니다.


답변