Modülde KeyError 'parçacığı' başarılı bir py sonra.testi
Py ile test kümesi koşuyorum.test. Geçerler. Yippie! Ama bu mesajı alıyorum:
Exception KeyError: KeyError(4427427920,) in <module 'threading' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.pyc'> ignored
Nasıl bu kaynağı takip gitmeli? (Doğrudan iş parçacığı kullanarak değilim, ama gevent kullanıyorum.)
CEVAP
Benzer bir sorun gözlemledim ve tam olarak neler yapılıyor sen bana bulguları tarif edeyim görmeye karar verdi. Birisi yararlı olacağını umuyoruz.
Kısa hikaye
Gerçekten maymun-yama threading
modülü ile ilgilidir. Aslında, kolay maymun-yama önce iş parçacığı iş parçacığı modülü alarak özel durum tetikleyebilir. Aşağıdaki 2 satır yeterli:
import threading
import gevent.monkey; gevent.monkey.patch_thread()
Çalıştırıldığında KeyError
göz ardı hakkında mesaj veriyor:
(env)czajnik@autosan:~$ python test.py
Exception KeyError: KeyError(139924387112272,) in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored
Eğer ithalat satırları değiştir, sorun yok.
Uzun hikaye
Benim hata ayıklama burada ben dururum, ama değer sorun kesin nedenini anlamak için karar verdim.
İlk adımdı göz ardı durum hakkında mesaj kodunu bulmak için. Oldu biraz benim için zor bulmak (grepping Exception.*ignored
elde bir şey yok), ama grepping etrafında CPython kaynak kodu buldum sonunda buldum bir fonksiyonu void PyErr_WriteUnraisable(PyObject *obj)
54* ile çok ilginç bir yorum:
/* Call when an exception has occurred but there is no way for Python
to handle it. Examples: exception in __del__ or during GC. */
Bunu kimin aradığını sadece aşağıdaki C-seviye yığın izleme için ** 16 yaşında, küçük bir yardım ile incelemeye karar verdim:
#0 0x0000000000542c40 in PyErr_WriteUnraisable ()
#1 0x00000000004af2d3 in Py_Finalize ()
#2 0x00000000004aa72e in Py_Main ()
#3 0x00007ffff68e576d in __libc_start_main (main=0x41b980 <main>, argc=2,
ubp_av=0x7fffffffe5f8, init=<optimized out>, fini=<optimized out>,
rtld_fini=<optimized out>, stack_end=0x7fffffffe5e8) at libc-start.c:226
#4 0x000000000041b9b1 in _start ()
Şimdi açıkça istisna Py_Finalize yürütür - bu ara Python yorumlayıcısı kapatma sorumlu iken, bellek, vb tahsis azat atılmış olduğunu görüyoruz. Sadece exitting önce deniyor.
Bir sonraki adım oldu Py_Finalize()
kod (Python/pythonrun.c) bak. Bunu yapan İlk Çağrı bu sorun, iş parçacığı ile ilgili olarak biz wait_for_thread_shutdown()
- bakmaya deÄŸer. Bu iÅŸlev _shutdown
threading
modülünde çağrı çağırır. İyi, python kodu için geri gidebiliriz.
threading.py
aşağıdaki ilginç bir parça buldum:
class _MainThread(Thread):
def _exitfunc(self):
self._Thread__stop()
t = _pickSomeNonDaemonThread()
if t:
if __debug__:
self._note("%s: waiting for other threads", self)
while t:
t.join()
t = _pickSomeNonDaemonThread()
if __debug__:
self._note("%s: exiting", self)
self._Thread__delete()
# Create the main thread object,
# and make it available for the interpreter
# (Py_Main) as threading._shutdown.
_shutdown = _MainThread()._exitfunc
Açıkça, threading._shutdown()
Ara sorumluluğu olmayan daemon bütün konuları katılmak ve ana iş parçacığı bu tam olarak ne anlama geliyorsa () silmek için. 27*/except
* threading.py
bir bit kaydırma _exitfunc()
tüm vücut yama yapmaya karar verdim ve traceback modül ile izleme yığını Yazdır. Bu aşağıdaki eser verdi
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 785, in _exitfunc
self._Thread__delete()
File "/usr/lib/python2.7/threading.py", line 639, in __delete
del _active[_get_ident()]
KeyError: 26805584
Şimdi hariç Thread.__delete()
yöntem içinde nereye atılır tam olarak nerede olduğunu biliyoruz.
Hikayenin geri kalanını bir süre için threading.py
okuduktan sonra açıktır. _active
sözlük haritalar parçacığı Kimliği _get_ident()
tarafından döndürülen gibi) oluşturulan tüm iş parçacıkları için Thread
örnekleri için. threading
modül yüklendiğinde, _MainThread
sınıfın bir örneği her zaman ve _active
eğer başka bir iş parçacığı açıkça oluşturulursa bile () için oluşturulan eklenir.
Sorun bu yöntem yamalı gevent
'In maymun-yama _get_ident()
- orijinal Haritalar için thread.get_ident()
maymun-yama deÄŸiÅŸtirir ile green_thread.get_ident()
. Belli ki her iki aramayı da ana iş parçacığı için farklı Kimlikleri verir.
Åžimdi, EÄŸer threading
modül yüklenmeden önce maymun-yama, _get_ident()
Ara bir deÄŸer verir _MainThread
örneği oluşturulur ve eklenen _active
ve baÅŸka bir deÄŸer de zaman _exitfunc()
denir - bu yüzden KeyError
48*.
Aksine, eğer maymun-yama yapılır önce threading
yüklenen, tüm iyi - zaman _MainThread
örnek ekleniyor _active
, _get_ident()
zaten yamalı ve aynı iş parçacığı KİMLİĞİ döndü temizleme zamanı. İşte bu!
Doğru sırayla modül alma emin olmak için, maymun-yama arayın hemen önce benim kod aşağıdaki kod ekledim,:
import sys
if 'threading' in sys.modules:
raise Exception('threading module loaded before patching!')
import gevent.monkey; gevent.monkey.patch_thread()
Benim hata ayıklama yararlı hikaye:) umarım bulursun
Bağlantı başarılı bir sunucu ama bir h...
İş için Birden çok iş Parçacığı tüm bi...
Nasıl daha sonra düz metin alma için e...
'Eclipse içine bir proje aldıktan...
Nasıl jQuery Ajax çağrısından sonra bi...