Saat ini saya memiliki modul pusat dalam kerangka kerja yang memunculkan beberapa proses menggunakan multiprocessing
modul Python 2.6 . Karena itu digunakan multiprocessing
, ada log tingkat-sadar multiprocessing modul LOG = multiprocessing.get_logger()
,. Per dokumen , logger ini memiliki kunci proses bersama sehingga Anda tidak memutarbalikkan hal-hal sys.stderr
(atau file apa pun yang ditangani) dengan meminta beberapa proses menulis secara bersamaan.
Masalah yang saya miliki sekarang adalah bahwa modul-modul lain dalam kerangka kerja ini tidak sadar multiprosesor. Cara saya melihatnya, saya perlu membuat semua dependensi pada modul pusat ini menggunakan pencatatan multiprocessing-aware. Itu menjengkelkan dalam kerangka kerja, apalagi untuk semua klien kerangka kerja. Apakah ada alternatif yang tidak saya pikirkan?
sumber
multiprocessing.get_logger()
? Tampaknya berdasarkan pada cara-cara lain untuk melakukan logging ini adalah fungsionalitas logging yangmultiprocessing
nilainya kecil.get_logger()
adalah logger yang digunakan olehmultiprocessing
modul itu sendiri. Berguna jika Anda ingin men-debugmultiprocessing
masalah.Jawaban:
Satu-satunya cara untuk menangani hal ini secara non-intrusively adalah dengan:
select
dari deskriptor file pipa, lakukan penggabungan-sort pada entri log yang tersedia, dan siram ke log terpusat. Ulangi.)sumber
atexit
:-). Masalahnya adalah itu tidak akan memberi Anda pembacaan waktu nyata. Ini mungkin merupakan bagian dari harga multiprocessing yang bertentangan dengan multithreading.multiprocessing.Queue
tidak akan lebih mudah jika ada banyak kode yang perlu dipasang kembali untuk digunakanmultiprocessing.Queue
, dan / atau jika kinerja merupakan masalahSaya baru saja menulis log handler saya sendiri yang hanya memberi makan segalanya untuk proses induk melalui pipa. Saya hanya mengujinya selama sepuluh menit tetapi tampaknya bekerja dengan cukup baik.
( Catatan: Ini adalah hardcoded
RotatingFileHandler
, yang merupakan kasus penggunaan saya sendiri.)Pembaruan: @javier sekarang mempertahankan pendekatan ini sebagai paket yang tersedia di Pypi - lihat multiprocessing-logging di Pypi, github di https://github.com/jruere/multiprocessing-logging
Perbarui: Implementasi!
Ini sekarang menggunakan antrian untuk penanganan konkurensi yang benar, dan juga pulih dari kesalahan dengan benar. Saya sekarang telah menggunakan ini dalam produksi selama beberapa bulan, dan versi saat ini di bawah ini berfungsi tanpa masalah.
sumber
multiprocessing.Queue
menggunakan utas untuk masukput()
. Jadi jangan memohonput
(mis. Log msg menggunakanMultiProcessingLog
handler) sebelum membuat semua subproses. Kalau tidak, utas akan mati dalam proses anak. Salah satu solusinya adalah meneleponQueue._after_fork()
pada awal setiap proses anak, atau menggunakannyamultiprocessing.queues.SimpleQueue
, yang tidak melibatkan utas tetapi menghalangi.multiprocessing-logging
.QueueHandler
adalah asli dalam Python 3.2+, dan melakukan hal ini. Ini mudah direplikasi di versi sebelumnya.Python docs memiliki dua contoh lengkap: Masuk ke satu file dari beberapa proses
Bagi mereka yang menggunakan Python <3.2, cukup salin
QueueHandler
ke kode Anda sendiri dari: https://gist.github.com/vsajip/591589 atau impor logutils alternatif .Setiap proses (termasuk proses induk) menempatkan logging pada
Queue
, dan kemudianlistener
utas atau proses (satu contoh disediakan untuk masing-masing) mengambil mereka dan menulis semuanya ke file - tidak ada risiko korupsi atau kekacauan.sumber
Di bawah ini adalah solusi lain dengan fokus pada kesederhanaan untuk orang lain (seperti saya) yang datang ke sini dari Google. Penebangan harus mudah! Hanya untuk 3,2 atau lebih tinggi.
sumber
QueueHandler
danQueueListener
kelas dapat digunakan pada Python 2,7 juga, tersedia dalamlogutils
paket.Namun alternatif lain mungkin berbagai penangan logging berbasis file dalam
logging
paket :SocketHandler
DatagramHandler
SyslogHandler
(dan lain-lain)
Dengan cara ini, Anda dapat dengan mudah memiliki daemon logging di suatu tempat yang dapat Anda tulis dengan aman dan akan menangani hasilnya dengan benar. (Misalnya, server soket sederhana yang hanya mengurai pesan dan memancarkannya ke penangan file rotasinya sendiri.)
The
SyslogHandler
akan mengurus ini untuk Anda juga. Tentu saja, Anda bisa menggunakan contoh Anda sendirisyslog
, bukan yang sistem.sumber
Varian yang lain yang membuat log logging dan antrian terpisah.
sumber
fileConfig()
di MainProcess dan logger yang hampir tidak dikonfigurasi di PoolWorkers (hanya dengansetLevel(logging.NOTSET)
) Seperti yang saya sebutkan di komentar lain, saya menggunakan Pool sehingga saya harus mendapatkan Antrian (proxy) saya dari Manajer alih-alih multiprocessing sehingga bisa diambil. Ini memungkinkan saya untuk mengantri ke pekerja di dalam kamus (sebagian besar berasal dari objek argsparse menggunakanvars()
). Saya merasa seperti pada akhirnya ini adalah pendekatan terbaik untuk MS Windows yang tidak memiliki fork () dan merusak solusi @zzzeak.fork
. Dengan begitu setiap proses akan memiliki antrian tidak berguna yang independen. Pendekatan kedua dalam Tanya Jawab terkait tidak akan berfungsi pada platform tersebut. Ini adalah cara untuk kode non-portabel.multiprocessing.Queue
dengan proses utama dan saya telah menggunakannya terus-menerus sejak itu. Tidak akan mengaku mengerti mengapa itu bekerja.Semua solusi saat ini terlalu digabungkan ke konfigurasi logging dengan menggunakan handler. Solusi saya memiliki arsitektur dan fitur berikut:
multiprocessing.Queue
logging.Logger
(dan contoh yang sudah ditentukan) ditambal untuk mengirim semua catatan ke antrianKode dengan contoh penggunaan dan keluaran dapat ditemukan di Intisari berikut: https://gist.github.com/schlamar/7003737
sumber
daemon_thread.daemon
untukTrue
. Saya perlu melakukan itu untuk mendapatkan program Python saya untuk keluar dengan benar ketika pengecualian terjadi dalam manajer konteks.func
dilogged_call
, jika pengecualian akan mendapatkan kacau dengan output bekas tebangan lainnya. Ini versi modifikasi saya tentang ini: gist.github.com/blah238/8ab79c4fe9cdb254f5c37abfc5dc85bfKarena kami dapat merepresentasikan multiprocess logging karena banyak penerbit dan satu pelanggan (pendengar), menggunakan ZeroMQ untuk mengimplementasikan pesan PUB-SUB memang merupakan pilihan.
Selain itu, modul PyZMQ , binding Python untuk ZMQ, mengimplementasikan PUBHandler , yang merupakan objek untuk mempublikasikan pesan logging melalui soket zmq.PUB.
Ada solusi di web , untuk logging terpusat dari aplikasi terdistribusi menggunakan PyZMQ dan PUBHandler, yang dapat dengan mudah diadopsi untuk bekerja secara lokal dengan berbagai proses penerbitan.
sumber
Saya juga suka jawaban zzzeek tetapi Andre benar bahwa antrian diperlukan untuk mencegah gangguan. Saya beruntung dengan pipa, tetapi memang melihat kekacauan yang agak diharapkan. Menerapkannya ternyata lebih sulit dari yang saya kira, terutama karena berjalan di Windows, di mana ada beberapa batasan tambahan tentang variabel dan hal-hal global (lihat: Bagaimana Proses Multi-Python Diimplementasikan pada Windows? )
Tapi, akhirnya aku berhasil. Contoh ini mungkin tidak sempurna, jadi komentar dan saran dipersilahkan. Itu juga tidak mendukung pengaturan formatter atau apa pun selain root logger. Pada dasarnya, Anda harus menginstal ulang logger di setiap proses kumpulan dengan antrian dan mengatur atribut lainnya pada logger.
Sekali lagi, saran tentang cara membuat kode lebih baik dipersilakan. Saya pasti belum tahu semua trik Python :-)
sumber
if 'MainProcess' == multiprocessing.current_process().name:
dapat digunakan sebagai pengganti passingchild
?cukup terbitkan di suatu tempat instance Anda dari logger. dengan begitu, modul dan klien lain dapat menggunakan API Anda untuk mendapatkan logger tanpa harus melakukannya
import multiprocessing
.sumber
import logging; logging.basicConfig(level=logging.DEBUG); logging.debug('spam!')
dari mana saja dan membuatnya berfungsi dengan baik.Saya menyukai jawaban zzzeek. Saya hanya akan mengganti Pipa untuk Antrian karena jika beberapa utas / proses menggunakan ujung pipa yang sama untuk menghasilkan pesan log mereka akan kacau.
sumber
Bagaimana dengan mendelegasikan semua pencatatan ke proses lain yang membaca semua entri log dari Antrian?
Cukup bagikan LOG_QUEUE melalui salah satu mekanisme multiproses atau bahkan warisan dan semuanya bekerja dengan baik!
sumber
Saya punya solusi yang mirip dengan ironhacker kecuali saya menggunakan logging.exception di beberapa kode saya dan menemukan bahwa saya perlu memformat pengecualian sebelum meneruskannya kembali ke Antrean karena traceback tidak dapat dipilih:
sumber
Di bawah ini adalah kelas yang dapat digunakan di lingkungan Windows, membutuhkan ActivePython. Anda juga bisa mewarisi untuk penangan logging lainnya (StreamHandler dll.)
Dan berikut ini adalah contoh yang menunjukkan penggunaan:
sumber
multiprocessing.Lock()
bukannya Mutex Windows akan membuat solusi portabel.Inilah solusi sederhana saya / pemecahan masalah ... bukan yang paling komprehensif, tetapi mudah dimodifikasi dan lebih sederhana untuk dibaca dan dipahami menurut saya daripada jawaban lain yang saya temukan sebelum menulis ini:
sumber
Ada paket bagus ini
Paket: https://pypi.python.org/pypi/multiprocessing-logging/
kode: https://github.com/jruere/multiprocessing-logging
Install:
Kemudian tambahkan:
sumber
Salah satu alternatifnya adalah menulis penebangan mutliprocessing ke file yang dikenal dan mendaftarkan
atexit
pawang untuk bergabung pada proses-proses tersebut membacanya kembali di stderr; namun, Anda tidak akan mendapatkan aliran waktu-nyata ke pesan keluaran di stderr dengan cara itu.sumber
Jika Anda memiliki kebuntuan yang terjadi dalam kombinasi kunci, utas dan garpu dalam
logging
modul, yang dilaporkan dalam laporan bug 6721 (lihat juga pertanyaan SO terkait ).Ada solusi perbaikan kecil yang diposting di sini .
Namun, itu hanya akan memperbaiki deadlock potensial di
logging
. Itu tidak akan memperbaiki hal-hal yang mungkin kacau. Lihat jawaban lain yang disajikan di sini.sumber
Ide paling sederhana seperti yang disebutkan:
[WatchedFileHandler][1]
. Alasan untuk pawang ini dibahas secara rinci di sini , tetapi singkatnya ada beberapa kondisi ras yang lebih buruk dengan pawang penebangan lainnya. Yang ini memiliki jendela terpendek untuk kondisi lomba.sumber
Untuk siapa pun yang mungkin membutuhkan ini, saya menulis dekorator untuk paket multiprocessing_logging yang menambahkan nama proses saat ini ke log, sehingga menjadi jelas siapa yang mencatat apa.
Itu juga menjalankan install_mp_handler () sehingga menjadi tidak berguna untuk menjalankannya sebelum membuat kumpulan.
Ini memungkinkan saya untuk melihat pekerja mana yang membuat pesan log mana.
Inilah cetak biru dengan contoh:
sumber
Kepada anak-anak saya yang mengalami masalah yang sama dalam beberapa dekade dan menemukan pertanyaan ini di situs ini saya meninggalkan jawaban ini.
Kesederhanaan vs rumit. Cukup gunakan alat lain. Python memang luar biasa, tetapi itu tidak dirancang untuk melakukan beberapa hal.
Cuplikan berikut untuk daemon logrotate berfungsi untuk saya dan tidak terlalu rumit. Jadwalkan untuk menjalankan setiap jam dan
Ini adalah bagaimana saya menginstalnya (symlink tidak berfungsi untuk logrotate):
sumber