Apa artinya 'terbunuh' saat pemrosesan CSV besar dengan Python, yang tiba-tiba berhenti?

94

Saya memiliki skrip Python yang mengimpor file CSV besar dan kemudian menghitung jumlah kemunculan setiap kata dalam file, kemudian mengekspor hitungan tersebut ke file CSV lain.

Tetapi apa yang terjadi adalah setelah bagian penghitungan selesai dan pengeksporan dimulai, katanya Killeddi terminal.

Saya tidak berpikir ini adalah masalah memori (jika saya berasumsi saya akan mendapatkan kesalahan memori dan bukan Killed).

Mungkinkah prosesnya terlalu lama? Jika ya, adakah cara untuk memperpanjang periode waktu tunggu sehingga saya dapat menghindari ini?

Ini kodenya:

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])

Dan yang Killedterjadi setelah finished countingdicetak, dan pesan lengkapnya adalah:

killed (program exited with code: 137)
pengguna1893354
sumber
6
Posting kata-kata yang tepat dari pesan kesalahan yang Anda dapatkan.
Robert Harvey
2
"terbunuh" secara umum berarti bahwa proses tersebut menerima beberapa sinyal yang menyebabkannya keluar. Dalam kasus ini karena terjadi pada saat yang sama dari skrip, ada kemungkinan besar itu adalah pipa yang rusak, proses mencoba membaca dari atau menulis ke pegangan file yang telah ditutup di ujung lainnya.
Andrew Clark
3
Ini bukan jawaban tentang dari mana killedpesan itu berasal, tetapi jika itu karena melewati beberapa jenis batas memori sistem, Anda mungkin dapat memperbaikinya dengan menggunakan counter.iteritems()alih-alih counter.items()di loop terakhir Anda. Di Python 2, itemskembalikan daftar kunci dan nilai dalam kamus, yang mungkin memerlukan banyak memori jika ukurannya sangat besar. Sebaliknya, iteritemsadalah generator yang hanya membutuhkan sedikit memori pada suatu waktu tertentu.
Blckknght

Jawaban:

104

Kode keluar 137 (128 + 9) menunjukkan bahwa program Anda keluar karena menerima sinyal 9, yaitu SIGKILL. Ini juga menjelaskan killedpesannya. Pertanyaannya adalah, mengapa Anda menerima sinyal itu?

Alasan yang paling mungkin adalah bahwa proses Anda melewati beberapa batasan dalam jumlah sumber daya sistem yang boleh Anda gunakan. Bergantung pada OS dan konfigurasi Anda, ini bisa berarti Anda memiliki terlalu banyak file yang terbuka, menggunakan terlalu banyak ruang filesytem atau yang lainnya. Kemungkinan besar adalah program Anda menggunakan terlalu banyak memori. Daripada mengambil risiko kerusakan ketika alokasi memori mulai gagal, sistem mengirim sinyal penghentian ke proses yang menggunakan terlalu banyak memori.

Seperti yang saya komentari sebelumnya, satu alasan Anda mungkin mencapai batas memori setelah mencetak finished countingadalah bahwa panggilan Anda ke counter.items()dalam loop terakhir Anda mengalokasikan daftar yang berisi semua kunci dan nilai dari kamus Anda. Jika kamus Anda memiliki banyak data, ini mungkin daftar yang sangat besar. Solusi yang mungkin counter.iteritems()adalah menggunakan generator. Daripada mengembalikan semua item dalam daftar, ini memungkinkan Anda mengulanginya dengan penggunaan memori yang jauh lebih sedikit.

Jadi, saya sarankan untuk mencoba ini, sebagai putaran terakhir Anda:

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

Perhatikan bahwa di Python 3, itemsmengembalikan objek "tampilan kamus" yang tidak memiliki overhead yang sama seperti versi Python 2. Ini menggantikan iteritems, jadi jika Anda nanti meningkatkan versi Python, Anda akan mengubah loop kembali seperti semula.

Blckknght
sumber
2
Benar, tetapi kamus itu sendiri juga akan memakan banyak memori. OP harus mempertimbangkan membaca dan memproses file secara bertahap, bukan sekaligus.
Kevin
24

Ada dua area penyimpanan yang terlibat: tumpukan dan heap. Tumpukan adalah tempat status saat ini dari panggilan metode disimpan (yaitu variabel dan referensi lokal), dan heap adalah tempat penyimpanan objek. rekursi dan memori

Saya rasa ada terlalu banyak kunci di counterdict yang akan menghabiskan terlalu banyak memori di wilayah heap, jadi runtime Python akan memunculkan pengecualian OutOfMemory .

Untuk menyimpannya, jangan membuat benda raksasa, misal meja penghitung .

1.StackOverflow

program yang membuat terlalu banyak variabel lokal.

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

sebuah program yang menciptakan raksasa dictmenyertakan terlalu banyak kunci.

>>> 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

Referensi
ROY
sumber
4

Kemungkinan besar, Anda kehabisan memori, sehingga Kernel mematikan proses Anda.

Pernahkah Anda mendengar tentang OOM Killer ?

Berikut adalah log dari skrip yang saya kembangkan untuk memproses sekumpulan besar data dari file 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

Itu diambil dari /var/log/syslog.

Pada dasarnya:

PID 12216 terpilih sebagai korban (karena penggunaan + 9Gb dari total-vm), jadi oom_killer menuai.

Berikut artikel tentang perilaku OOM .

ivanleoncz.dll
sumber
1
1, hanya untuk memperjelas, untuk memahami berapa banyak RAM yang coba digunakan program saya, haruskah saya menambahkan nilai total-vm, anon-rss, file-rss? Juga dan total-vm memberikan berapa banyak program saya menggunakan dan bukan memori aktual yang tersedia, bukan? Maaf, pengetahuan terbatas.
momo
1
Pengetahuan saya juga terbatas pada konteks ini, @momo. Saya sedikit kehabisan waktu untuk penyelidikan lebih lanjut, tetapi saya menemukan posting ini yang mungkin membantu: stackoverflow.com/questions/18845857/… . Apa yang dapat saya katakan kepada Anda, adalah, total-vm, adalah jumlah memori yang digunakan oleh proses tersebut.
ivanleoncz
3

Saya ragu ada yang bisa menghentikan proses hanya karena butuh waktu lama. Killed secara umum berarti sesuatu dari luar menghentikan proses, tetapi mungkin tidak dalam kasus ini menekan Ctrl-C karena itu akan menyebabkan Python keluar pada pengecualian KeyboardInterrupt. Selain itu, dengan Python Anda akan mendapatkan pengecualian MemoryError jika itu masalahnya. Apa yang mungkin terjadi adalah Anda terkena bug dengan Python atau kode pustaka standar yang menyebabkan crash proses.

Wingware
sumber
Bug yang menabrak akan jauh lebih mungkin menghasilkan segfault daripada mendapatkan SIGKILL, kecuali Python memiliki suatu raise(SIGKILL)tempat dalam kodenya karena alasan tertentu.
Kevin
1
Bug di python tidak akan mengirim SIGKILL.
qwr
1

Saya baru saja mengalami hal yang sama pada saya ketika saya mencoba menjalankan skrip python dari folder bersama di VirtualBoxdalam Ubuntu 20.04 LTS yang baru. Python ditebus dengan Killedsaat memuat perpustakaan pribadi saya. Saat saya memindahkan folder ke direktori lokal, masalahnya hilang. Tampaknya Killedpenghentian terjadi selama impor awal perpustakaan saya karena saya mendapat pesan tentang perpustakaan yang hilang begitu saya memindahkan folder.

Masalahnya hilang setelah saya menyalakan ulang komputer saya.

Oleh karena itu, orang-orang mungkin ingin mencoba memindahkan program ke direktori lokal jika itu lebih dari satu jenis atau bisa jadi masalah sementara yang hanya membutuhkan reboot OS.

Timothy C. Quinn
sumber
Tunggu, Anda harus mereboot host atau VM Anda?
cglacet
1
Iya. Dalam kasus saya, saya sedang membangun VM baru dan saya baru saja menginstal Python ketika saya melihat masalah ini. Setelah reboot, itu hilang. Saya benci mem-boot ulang sebagai cara untuk memperbaiki berbagai hal jadi saya menghabiskan banyak waktu mencoba men-debug dan setelah satu jam menggali, termasuk di sini di SO. Tapi akhirnya, saya menyerah dan reboot dan presto. Saya tidak tahu mengapa itu berhasil.
Timothy C. Quinn