Python ile devasa bir CSV'nin işlenmesi aniden durduğunda 'öldürülmüş' ne demektir?


94

Büyük bir CSV dosyasını içe aktaran ve ardından dosyadaki her kelimenin geçtiği sayıları sayan, ardından sayıları başka bir CSV dosyasına aktaran bir Python komut dosyam var.

Ama olan şu ki, bu sayım kısmı bitip ihracat başladığında Killedterminalde diyor .

Bunun bir hafıza sorunu olduğunu sanmıyorum (eğer öyleyse bir hafıza hatası alacağımı ve almayacağımı varsayarsam Killed).

Süreç çok uzun sürüyor olabilir mi? Öyleyse, zaman aşımı süresini uzatmanın bir yolu var mı?

İşte kod:

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

Ve yazdırıldıktan Killedsonra olur finished countingve mesajın tamamı:

killed (program exited with code: 137)

6
Aldığınız hata mesajının tam metnini yayınlayın.
Robert Harvey

2
"öldürüldü" genellikle işlemin çıkışına neden olan bir sinyal aldığı anlamına gelir. Bu durumda, komut dosyası ile aynı anda gerçekleştiği için, borunun kırık olma ihtimali yüksektir, işlem diğer uçta kapatılmış bir dosya tanıtıcısından okumaya veya ona yazmaya çalışmaktadır.
Andrew Clark

3
killedMesajın nereden geldiği ile ilgili bir cevap değil , ancak bir tür sistem hafıza sınırını aşmaktan kaynaklanıyorsa, bunu son döngünüz counter.iteritems()yerine kullanarak düzeltebilirsiniz counter.items(). Python 2'de, itemssözlükteki anahtarların ve değerlerin bir listesini döndürür; bu, çok büyükse çok fazla bellek gerektirebilir. Aksine, iteritemsherhangi bir zamanda yalnızca küçük miktarda bellek gerektiren bir jeneratördür.
Blckknght

Yanıtlar:


104

Çıkış kodu 137 (128 + 9), programınızdan çıkan sinyal 9 nedeniyle çıkıldığını gösterir SIGKILL. Bu aynı zamanda killedmesajı da açıklıyor . Soru şu ki, bu sinyali neden aldın?

Bunun en olası nedeni, muhtemelen işleminizin, kullanmanıza izin verilen sistem kaynakları miktarında bir sınırı aşmasıdır. İşletim sisteminize ve yapılandırmanıza bağlı olarak bu, çok fazla açık dosyanız olduğu, çok fazla dosya sistemi alanı veya başka bir şey kullandığınız anlamına gelebilir. Büyük olasılıkla programınız çok fazla bellek kullanıyordu. Bellek ayırmaları başarısız olmaya başladığında işlerin kırılma riskini almak yerine, sistem çok fazla bellek kullanan işleme bir sonlandırma sinyali gönderdi.

Daha önce de belirttiğim gibi, yazdırdıktan sonra bir bellek sınırına ulaşmanızın bir nedeni , son döngünüzdeki finished countingçağrınızın counter.items()sözlüğünüzdeki tüm anahtarları ve değerleri içeren bir liste ayırmasıdır. Sözlüğünüzde çok fazla veri varsa, bu çok büyük bir liste olabilir. Olası bir çözüm counter.iteritems(), bir jeneratör olanı kullanmak olacaktır . Bir listedeki tüm öğeleri döndürmek yerine, çok daha az bellek kullanımıyla bunların üzerinde yineleme yapmanızı sağlar.

Bu yüzden, son döngünüz olarak şunu denemenizi öneririm:

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

Python 3'te, itemsPython 2'nin sürümüyle aynı ek yüke sahip olmayan bir "sözlük görünümü" nesnesi döndürdüğüne dikkat edin. Yerini alır iteritems, böylece daha sonra Python sürümlerini yükseltirseniz, döngüyü eski haline geri döndürürsünüz.


2
Doğru, ancak sözlüğün kendisi de çok fazla hafıza kaplayacaktır. OP, dosyayı bir kerede okumak yerine aşamalı olarak okumayı ve işlemeyi düşünmelidir.
Kevin

24

İlgili iki depolama alanı vardır: yığın ve yığın. Yığın, bir yöntem çağrısının mevcut durumunun (yani yerel değişkenler ve referanslar) tutulduğu yerdir ve yığın, nesnelerin depolandığı yerdir. özyineleme ve hafıza

Tahminimde counteryığın bölgesinin çok fazla belleğini tüketecek çok fazla anahtar var , bu yüzden Python çalışma zamanı bir OutOfMemory yükseltecek istisnası oluşturacaktır.

Kaydetmek için devasa bir nesne oluşturmayın, örneğin tezgah .

1. Yığın Taşması

çok fazla yerel değişken oluşturan bir program.

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

Dev yaratan bir program dictçok fazla anahtar içerir.

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

Referanslar

4

Büyük ihtimalle hafızanız tükendi, bu nedenle Çekirdek sürecinizi öldürdü.

OOM Katilini duydun mu mu?

CSV dosyalarından çok sayıda veriyi işlemek için geliştirdiğim bir komut dosyasından bir günlük:

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

... 'dan alındı /var/log/syslog .

Temel olarak:

PID 12216 kurban olarak seçildi (+ 9Gb toplam vm kullanması nedeniyle), bu yüzden oom_killer bunu biçti .

İşte OOM davranışı hakkında bir makale .


1
+1, sadece açıklığa kavuşturmak için, programımın ne kadar RAM kullanmaya çalıştığını anlamak için total-vm, anon-rss, file-rss değerlerini toplamalı mıyım? Ayrıca ve total-vm, programımın gerçek kullanılabilir belleği değil ne kadar kullandığını gösteriyor, değil mi? Üzgünüm, sınırlı bilgi.
momo

1
Bu bağlamda bilgim de sınırlıdır, @momo. Daha fazla araştırma yapmak için biraz zamanım yok, ancak yardımcı olabilecek şu gönderiyi buldum: stackoverflow.com/questions/18845857/… . Size söyleyebileceğim şey, aslında toplam vm, işlem tarafından kullanılan bellek miktarıdır.
ivanleoncz

3

Uzun bir zaman aldığı için herhangi bir şeyin süreci öldürdüğünden şüpheliyim. Killed, genel olarak dışarıdan bir şeyin işlemi sonlandırdığı anlamına gelir, ancak muhtemelen bu durumda Ctrl-C'ye basmak değil, çünkü bu Python'un bir KeyboardInterrupt istisnasında çıkmasına neden olur. Ayrıca, Python'da sorun buysa MemoryError istisnası alırsınız. Olan şey, Python'da veya standart kitaplık kodunda işlemin çökmesine neden olan bir hataya çarpmanız olabilir.


SIGKILLPython herhangi bir raise(SIGKILL)nedenle kodunda bir yere sahip değilse, çökmekte olan bir hatanın elde etmekten çok bir segfault ile sonuçlanması daha olasıdır .
Kevin

1
Python'daki bir hata SIGKILL göndermez.
qwr

1

VirtualBoxYeni Ubuntu 20.04 LTS'de paylaşılan bir klasörden bir python betiği çalıştırmaya çalıştığımda da aynısını yaşadım . Python, Killedkendi kişisel kitaplığımı yüklerken kurtuldu . Klasörü yerel bir dizine taşıdığımda sorun ortadan kalktı. KilledKlasörü taşıdığımda eksik kitaplıklarla ilgili mesajlar aldığım için durma, kitaplığımın ilk içe aktarımı sırasında gerçekleşmiş gibi görünüyor .

Bilgisayarımı yeniden başlattıktan sonra sorun ortadan kalktı.

Bu nedenle, insanlar bir tür paylaşımın üzerinde ise programı yerel bir dizine taşımayı deneyebilir veya bu, işletim sisteminin yeniden başlatılmasını gerektiren geçici bir sorun olabilir.


Bekle, ana makinenizi veya sanal makinenizi yeniden mi başlatmak zorunda kaldınız?
cglacet

1
Evet. Benim durumumda, yeni bir VM oluşturuyordum ve bu sorunu gördüğümde Python'u yeni kurmuştum. Yeniden başlattıktan sonra kayboldu. Bir şeyleri düzeltmenin bir yolu olarak yeniden başlatmaktan nefret ediyorum, bu yüzden burada SO'da da dahil olmak üzere, hata ayıklamaya çalışırken ve bir saat kazı yaptıktan sonra bir sürü zaman harcadım. Ama sonunda pes ettim ve yeniden başlattım ve presto. Neden işe yaradığına dair hiçbir fikrim yok.
Timothy C. Quinn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.