Menampilkan jejak stack dari aplikasi Python yang sedang berjalan


340

Saya memiliki aplikasi Python ini yang macet dari waktu ke waktu dan saya tidak tahu di mana.

Apakah ada cara untuk memberi sinyal juru bahasa Python untuk menunjukkan kepada Anda kode persis yang sedang berjalan?

Semacam stacktrace on-the-fly?

Pertanyaan-pertanyaan Terkait:



Jawaban:


315

Saya memiliki modul yang saya gunakan untuk situasi seperti ini - di mana suatu proses akan berjalan untuk waktu yang lama tetapi kadang-kadang macet karena alasan yang tidak diketahui dan tidak dapat direproduksi. Agak aneh, dan hanya berfungsi di unix (memerlukan sinyal):

import code, traceback, signal

def debug(sig, frame):
    """Interrupt running process, and provide a python prompt for
    interactive debugging."""
    d={'_frame':frame}         # Allow access to frame object.
    d.update(frame.f_globals)  # Unless shadowed by global
    d.update(frame.f_locals)

    i = code.InteractiveConsole(d)
    message  = "Signal received : entering python shell.\nTraceback:\n"
    message += ''.join(traceback.format_stack(frame))
    i.interact(message)

def listen():
    signal.signal(signal.SIGUSR1, debug)  # Register handler

Untuk menggunakannya, panggil saja fungsi listen () di beberapa titik ketika program Anda dijalankan (Anda bahkan bisa menempelkannya di site.py agar semua program python menggunakannya), dan biarkan dijalankan. Kapan saja, kirim proses sinyal SIGUSR1, menggunakan kill, atau dengan python:

    os.kill(pid, signal.SIGUSR1)

Ini akan menyebabkan program memecah konsol python pada titik saat ini, menunjukkan jejak stack, dan membiarkan Anda memanipulasi variabel. Gunakan control-d (EOF) untuk terus berjalan (meskipun perhatikan bahwa Anda mungkin akan mengganggu I / O dll pada titik yang Anda beri sinyal, sehingga tidak sepenuhnya tidak mengganggu.

Saya punya skrip lain yang melakukan hal yang sama, kecuali itu berkomunikasi dengan proses yang berjalan melalui pipa (untuk memungkinkan proses debugging latar belakang dll). Agak besar untuk memposting di sini, tapi saya telah menambahkannya sebagai resep buku resep python .


1
Terima kasih! Inilah yang saya cari. Mungkin Anda juga bisa memposting skrip itu dengan dukungan pipa di beberapa situs snippet Python?
Seb

2
Saya sekarang telah mempostingnya di situs buku resep python - tautan ditambahkan.
Brian

1
Saya perlu menambahkan "import readline" untuk mengaktifkan fitur histori.
miracle2k

2
Tip yang bagus! Ini juga berfungsi untuk mengirim sinyal, ke semua proses yang mengandung kata "mypythonapp": pkill -SIGUSR1 -f mypythonapp
Alexander

10
Jika aplikasi macet, loop interpreter Python mungkin tidak dapat berjalan untuk memproses sinyal. Gunakan faulthandlermodul (dan backport-nya yang ditemukan di PyPI) untuk penangan sinyal level C yang akan mencetak tumpukan Python tanpa memerlukan loop interpreter untuk menjadi responsif.
gps

146

Saran untuk memasang pengendali sinyal adalah saran yang bagus, dan saya sering menggunakannya. Misalnya, bzr secara default menginstal pawang SIGQUIT yang memanggil pdb.set_trace()untuk segera menjatuhkan Anda ke prompt pdb . (Lihat sumber modul bzrlib.breakin untuk detail yang tepat.) Dengan pdb Anda tidak hanya bisa mendapatkan jejak stack saat ini tetapi juga memeriksa variabel, dll.

Namun, kadang-kadang saya perlu men-debug proses yang saya tidak memiliki pandangan jauh ke depan untuk menginstal handler sinyal masuk. Di linux, Anda dapat melampirkan gdb ke proses dan mendapatkan jejak tumpukan python dengan beberapa makro gdb. Masukan http://svn.python.org/projects/python/trunk/Misc/gdbinit di ~/.gdbinit, maka:

  • Lampirkan gdb: gdb -p PID
  • Dapatkan jejak tumpukan python: pystack

Sayangnya, ini tidak sepenuhnya dapat diandalkan, tetapi sebagian besar berfungsi.

Akhirnya, melampirkan stracesering dapat memberi Anda ide bagus tentang apa yang dilakukan suatu proses.


2
Cemerlang! Perintah pystack kadang-kadang terkunci, tetapi sebelum itu memberi saya jejak stack lengkap dari proses, dalam baris kode python, tanpa perlu melakukan persiapan apa pun.
muudscope

26
Pembaruan kecil: teknik gdb ini (dan kode yang diperbarui) didokumentasikan di wiki.python.org/moin/DebuggingWithGdb Ada beberapa perkembangan di bagian depan ini, didokumentasikan pada URL itu, dan tampaknya gdb 7 memiliki beberapa dukungan Python.
Nelson

7
Sejauh yang saya tahu, ini hanya benar-benar berfungsi jika Anda memiliki simbol debug dikompilasi ke dalam biner python Anda - misalnya: Anda menjalankan program Anda dengan python2-dbg (di Ubuntu, ini dalam paket terpisah python-dbg). Tanpa simbol-simbol itu, Anda sepertinya tidak mendapatkan banyak informasi berguna.
drevicko

1
dalam kasus saya ini kembali Unable to locate python frameke setiap perintah
seriyPS

6
gdb 7+ --dengan dukungan python disediakan oleh python-gdb.py. Lebih detail di sini: chezsoi.org/lucas/blog/2014/11/07/en-gdb-python-macros
Lucas Cimon

71

Saya hampir selalu berurusan dengan banyak utas dan utas utama umumnya tidak melakukan banyak hal, jadi yang paling menarik adalah membuang semua tumpukan (yang lebih mirip dump Java). Berikut ini adalah implementasi berdasarkan blog ini :

import threading, sys, traceback

def dumpstacks(signal, frame):
    id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
    code = []
    for threadId, stack in sys._current_frames().items():
        code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), threadId))
        for filename, lineno, name, line in traceback.extract_stack(stack):
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    print "\n".join(code)

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

53

Mendapatkan jejak stack dari program python yang tidak siap , berjalan di stock python tanpa simbol debugging dapat dilakukan dengan pyrasite . Bekerja seperti pesona bagi saya di Ubuntu Trusty:

$ sudo pip install pyrasite
$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
$ sudo pyrasite 16262 dump_stacks.py # dumps stacks to stdout/stderr of the python program

(Hat tip ke @Albert, yang jawabannya berisi petunjuk untuk ini, di antara alat-alat lain.)


5
Ini bekerja sangat baik untuk saya, di mana dump_stacks.pysederhananyaimport traceback; traceback.print_stack()
John Lehmann

2
traceback -lmemberi Anda daftar skrip python standar yang dapat Anda gunakan, dan dump_stacks.pymerupakan salah satunya. Jika Anda menggunakan milik Anda sendiri (misalnya untuk menulis jejak stack ke file) mungkin bijaksana untuk menggunakan nama yang berbeda.
johndodo

12
Tip penting: jalankan apt-get install gdb python-dbg(atau setara) sebelum menjalankan pyrasite, jika tidak maka diam-diam akan gagal. Sebaliknya, berfungsi seperti mantra!
johndodo

Rilis terakhir pyrasite adalah pada tahun 2012
Boris

35
>>> import traceback
>>> def x():
>>>    print traceback.extract_stack()

>>> x()
[('<stdin>', 1, '<module>', None), ('<stdin>', 2, 'x', None)]

Anda juga dapat memformat jejak tumpukan dengan baik, lihat dokumen .

Sunting : Untuk mensimulasikan perilaku Java, seperti yang disarankan oleh @Douglas Leeder, tambahkan ini:

import signal
import traceback

signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))

ke kode startup di aplikasi Anda. Kemudian Anda dapat mencetak tumpukan dengan mengirim SIGUSR1ke proses Python yang sedang berjalan.


2
Ini hanya akan mencetak jejak balik utas utama. Saya belum menemukan solusi untuk melihat jejak untuk semua utas. Bahkan, python tampaknya tidak memiliki API untuk mengambil stack dari objek Thread, meskipun threading.enumerate () memberikan akses ke semua objek Thread.
haridsv

Ini sangat bagus di cygwin. Ini hanya mencetak tiga baris jejak tumpukan, tapi itu cukup untuk mendapatkan petunjuk
slashdottir

28

The traceback modul memiliki beberapa fungsi yang bagus, di antaranya: print_stack:

import traceback

traceback.print_stack()

1
Untuk menulis jejak stack ke file gunakan: import traceback; f = open('/tmp/stack-trace.log', 'w') traceback.print_stack(file=f) f.close()
GuruM

1
+1 ke @gulgi untuk jawabannya yang mudah digunakan. Beberapa jawaban lain tampak sangat rumit untuk tugas sederhana saya mendapatkan jejak panggilan-stack dari fungsi skrip.
GuruM

24

Anda dapat mencoba modul faulthandler . Instal menggunakan pip install faulthandlerdan tambahkan:

import faulthandler, signal
faulthandler.register(signal.SIGUSR1)

di awal program Anda. Kemudian kirim SIGUSR1 ke proses Anda (mis .:) kill -USR1 42untuk menampilkan traceback Python semua utas ke keluaran standar. Baca dokumentasi untuk opsi lebih lanjut (mis: masuk ke file) dan cara lain untuk menampilkan traceback.

Modul ini sekarang merupakan bagian dari Python 3.3. Untuk Python 2, lihat http://faulthandler.readthedocs.org/


20

Apa yang benar-benar membantu saya di sini adalah tip spiv (yang akan saya pilih dan komentari jika saya memiliki poin reputasi) untuk mendapatkan jejak stack dari proses Python yang tidak siap . Kecuali itu tidak berfungsi sampai saya memodifikasi skrip gdbinit . Begitu:

  • unduh http://svn.python.org/projects/python/trunk/Misc/gdbinit dan masukkan~/.gdbinit

  • edit, ubah PyEval_EvalFramemenjadiPyEval_EvalFrameEx[edit: tidak lagi diperlukan; file tertaut sudah memiliki perubahan ini pada 2010-01-14]

  • Lampirkan gdb: gdb -p PID

  • Dapatkan jejak tumpukan python: pystack


Gdbinit di URL yang disebutkan itu tampaknya sudah memiliki tambalan yang Anda sarankan. Dalam kasus saya, ketika saya mengetik pystack CPU saya hanya hang. Tidak yakin kenapa.
Jesse Glick

2
Tidak, tidak - saya tidak jelas, maaf, karena garis itu muncul di tiga tempat. Tambalan yang saya tautkan ke pertunjukan mana yang telah saya ubah ketika saya melihat karya ini.
Gunnlaugur Briem

2
Seperti jawaban @ spiv, ini membutuhkan program untuk berjalan di bawah python yang dikompilasi dengan simbol debugging. Kalau tidak, Anda hanya akan mendapatkanNo symbol "co" in current context.
Nickolay

12

Saya akan menambahkan ini sebagai komentar untuk tanggapan haridsv , tetapi saya tidak memiliki reputasi untuk melakukannya:

Beberapa dari kita masih terjebak pada versi Python yang lebih tua dari 2,6 (diperlukan untuk Thread.ident), jadi saya mendapatkan kode yang berfungsi di Python 2.5 (meskipun tanpa nama utas yang ditampilkan) seperti:

import traceback
import sys
def dumpstacks(signal, frame):
    code = []
    for threadId, stack in sys._current_frames().items():
            code.append("\n# Thread: %d" % (threadId))
        for filename, lineno, name, line in traceback.extract_stack(stack):
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    print "\n".join(code)

import signal
signal.signal(signal.SIGQUIT, dumpstacks)

11

python -dv yourscript.py

Itu akan membuat penerjemah berjalan dalam mode debug dan memberi Anda jejak apa yang dilakukan penerjemah.

Jika Anda ingin men-debug kode secara interaktif, Anda harus menjalankannya seperti ini:

python -m pdb yourscript.py

Itu memberi tahu interpreter python untuk menjalankan skrip Anda dengan modul "pdb" yang merupakan debugger python, jika Anda menjalankannya seperti itu interpreter akan dieksekusi dalam mode interaktif, seperti halnya GDB


Ini tidak menjawab pertanyaan. Pertanyaannya adalah tentang proses yang sudah berjalan.
dbn

11

Lihatlah faulthandlermodul, baru dalam Python 3.3. Sebuah faulthandlerbackport untuk digunakan dalam Python 2 tersedia di PyPI.


2
Jawaban yang lebih baru oleh @haypo membahas hal ini lebih terinci. Saya tidak yakin bagaimana ini biasanya ditangani pada SO, tetapi rasanya salah untuk memiliki dua jawaban yang pada dasarnya duplikat ...
Nickolay

7

Pada Solaris, Anda dapat menggunakan pstack (1) Tidak diperlukan perubahan pada kode python. misalnya.

# pstack 16000 | grep : | head
16000: /usr/bin/python2.6 /usr/lib/pkg.depotd --cfg svc:/application/pkg/serv
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:282 (_wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:295 (wait) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/process/wspbus.py:242 (block) ]
[ /usr/lib/python2.6/vendor-packages/cherrypy/_init_.py:249 (quickstart) ]
[ /usr/lib/pkg.depotd:890 (<module>) ]
[ /usr/lib/python2.6/threading.py:256 (wait) ]
[ /usr/lib/python2.6/Queue.py:177 (get) ]
[ /usr/lib/python2.6/vendor-packages/pkg/server/depot.py:2142 (run) ]
[ /usr/lib/python2.6/threading.py:477 (run)
etc.

2
Tampaknya ada program Debian / Ubuntu pstackyang melakukan hal yang sama
Rory

1
Tampaknya hanya memberikan backtrace di linux, bukan traceback Python dengan nama file dan nomor baris.
ogrisel

6

Jika Anda menggunakan sistem Linux, gunakan kehebatan gdbdengan ekstensi debug Python (bisa di python-dbgataupython-debuginfo paket). Ini juga membantu dengan aplikasi multithreaded, aplikasi GUI dan modul C.

Jalankan program Anda dengan:

$ gdb -ex r --args python <programname>.py [arguments]

Ini menginstruksikan gdbuntuk mempersiapkan python <programname>.py <arguments>dan rmelepaskannya.

Sekarang ketika Anda memprogram hang, beralih ke gdbkonsol, tekan Ctr+Cdan jalankan:

(gdb) thread apply all py-list

Lihat contoh sesi dan info lebih lanjut di sini dan di sini .


6

Saya mencari solusi untuk men-debug thread saya dan saya menemukannya di sini berkat haridsv. Saya menggunakan versi yang sedikit disederhanakan menggunakan traceback.print_stack ():

import sys, traceback, signal
import threading
import os

def dumpstacks(signal, frame):
  id2name = dict((th.ident, th.name) for th in threading.enumerate())
  for threadId, stack in sys._current_frames().items():
    print(id2name[threadId])
    traceback.print_stack(f=stack)

signal.signal(signal.SIGQUIT, dumpstacks)

os.killpg(os.getpgid(0), signal.SIGQUIT)

Untuk kebutuhan saya, saya juga memfilter utas berdasarkan nama.


3

Layak untuk melihat Pydb , "versi diperluas dari Python debugger longgar berdasarkan pada set perintah gdb". Ini termasuk manajer sinyal yang dapat memulai debugger ketika sinyal tertentu dikirim.

Proyek Summer of Code 2006 melihat penambahan fitur debugging jarak jauh ke pydb dalam modul yang disebut mpdb .


Tampaknya sudah melalui dua ( 1 ) penulisan ulang ( 2 ) tanpa menambahkan fitur attach-by-PID yang saya cari ...
Nickolay

3

Saya meretas beberapa alat yang terhubung ke proses Python yang sedang berjalan dan menyuntikkan beberapa kode untuk mendapatkan kulit Python.

Lihat di sini: https://github.com/albertz/pydbattach


1
Catatan: tidak jelas cara membangun ini. Terima kasih atas tautan yang Anda masukkan ke README: pyrasitebekerja dengan sempurna!
Nickolay

3

Ini dapat dilakukan dengan mata-mata yang sangat baik . Ini adalah profiler pengambilan sampel untuk program Python , jadi tugasnya adalah melampirkan ke proses Python dan mencicipi tumpukan panggilan mereka. Oleh karena itu, py-spy dump --pid $SOME_PIDsemua yang perlu Anda lakukan untuk membuang tumpukan panggilan dari semua utas dalam $SOME_PIDproses. Biasanya diperlukan peningkatan hak (untuk membaca memori proses target ').

Berikut ini contoh tampilannya untuk aplikasi Python berulir.

$ sudo py-spy dump --pid 31080
Process 31080: python3.7 -m chronologer -e production serve -u www-data -m
Python v3.7.1 (/usr/local/bin/python3.7)

Thread 0x7FEF5E410400 (active): "MainThread"
    _wait (cherrypy/process/wspbus.py:370)
    wait (cherrypy/process/wspbus.py:384)
    block (cherrypy/process/wspbus.py:321)
    start (cherrypy/daemon.py:72)
    serve (chronologer/cli.py:27)
    main (chronologer/cli.py:84)
    <module> (chronologer/__main__.py:5)
    _run_code (runpy.py:85)
    _run_module_as_main (runpy.py:193)
Thread 0x7FEF55636700 (active): "_TimeoutMonitor"
    run (cherrypy/process/plugins.py:518)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)
Thread 0x7FEF54B35700 (active): "HTTPServer Thread-2"
    accept (socket.py:212)
    tick (cherrypy/wsgiserver/__init__.py:2075)
    start (cherrypy/wsgiserver/__init__.py:2021)
    _start_http_thread (cherrypy/process/servers.py:217)
    run (threading.py:865)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)
...
Thread 0x7FEF2BFFF700 (idle): "CP Server Thread-10"
    wait (threading.py:296)
    get (queue.py:170)
    run (cherrypy/wsgiserver/__init__.py:1586)
    _bootstrap_inner (threading.py:917)
    _bootstrap (threading.py:885)  

2

pyringe adalah debugger yang dapat berinteraksi dengan menjalankan proses python, mencetak jejak stack, variabel, dll. tanpa pengaturan apriori.

Meskipun saya sering menggunakan solusi penangan sinyal di masa lalu, masih sering kali sulit untuk mereproduksi masalah di lingkungan tertentu.


3
Tampaknya itu tidak kompatibel dengan build gdb tertentu (mis. Yang saya instal di ubuntu): github.com/google/pyringe/issues/16 , membutuhkan pembangunan kembali secara manual. Debugger lain pyrasite,, bekerja seperti pesona bagi saya.
Nickolay

1

Tidak ada cara untuk menghubungkan ke proses python berjalan dan mendapatkan hasil yang masuk akal. Apa yang saya lakukan jika proses mengunci adalah mengaitkan strace dan mencoba mencari tahu apa yang sebenarnya terjadi.

Sayangnya sering strace adalah pengamat yang "memperbaiki" kondisi balapan sehingga hasilnya juga tidak berguna di sana.


1
Ya ini benar. Sangat memalukan meskipun pdb ini tidak mendukung melampirkan ke proses yang berjalan ...
Bartosz Radaczyński

Ini tidak benar. Lihat jawaban dengan "spiv" di atas, yang menunjukkan cara menghubungkan gdb dan mendapatkan jejak tumpukan Python.
andrew cooke

Tidak sama - makro gdb tidak dapat diandalkan dan tidak menyediakan antarmuka pdb yang penuh daya / familiar. Saya sering berharap seseorang menulis aplikasi kecil yang akan menggunakan ptrace untuk menyuntikkan beberapa bytecode Python ke dalam proses Python yang sedang berjalan dan memerintahkannya menjalankan 'import pdb; pdb.set_trace () ', mungkin juga setelah sementara mengalihkan sys.stdin / stdout.
Marius Gedminas

Ini tidak benar lagi, lihat jawaban lain yang menunjuk pada pyringe / pyrasite.
Nickolay

1

Anda dapat menggunakan PuDB , debugger Python dengan antarmuka kutukan untuk melakukan ini. Cukup tambahkan

from pudb import set_interrupt_handler; set_interrupt_handler()

ke kode Anda dan gunakan Ctrl-C ketika Anda ingin istirahat. Anda dapat melanjutkan cdan memecahkan lagi beberapa kali jika Anda melewatkannya dan ingin mencoba lagi.


Ketika Anda menggunakan perintah di atas dalam Django, jangan lupa untuk menjalankan server dengan benar untuk mencegah gangguan: "manage.py runserver --noreload --nothreading"
potar

1

Saya di kamp GDB dengan ekstensi python. Ikuti https://wiki.python.org/moin/DebuggingWithGdb , yang artinya

  1. dnf install gdb python-debuginfo atau sudo apt-get install gdb python2.7-dbg
  2. gdb python <pid of running process>
  3. py-bt

Juga pertimbangkan info threadsdan thread apply all py-bt.


adalah normal untuk mendapatkan respon seperti Traceback (most recent call first): Python Exception <class 'gdb.error'> No frame is currently selected.: Error occurred in Python command: No frame is currently selected.saat menjalankan py-btdi gdb?
crookedleaf

1
sudahlah. itu karena aplikasi saya berjalan sebagai sudo. saya perlu menjalankan gdb pyton <pid>sebagai sudo juga.
crookedleaf

1

Cara debug fungsi apa saja di konsol :

Buat fungsi tempat Anda menggunakan pdb.set_trace () , lalu fungsi yang Anda inginkan untuk debug.

>>> import pdb
>>> import my_function

>>> def f():
...     pdb.set_trace()
...     my_function()
... 

Kemudian panggil fungsi yang dibuat:

>>> f()
> <stdin>(3)f()
(Pdb) s
--Call--
> <stdin>(1)my_function()
(Pdb) 

Selamat men-debug :)


0

Saya tidak tahu apa pun yang mirip dengan respons java terhadap SIGQUIT , jadi Anda mungkin harus membuatnya di dalam aplikasi Anda. Mungkin Anda bisa membuat server di utas lain yang bisa mendapatkan stacktrace tentang respons terhadap suatu pesan?


0

gunakan modul inspect.

impor periksa bantuan (inspect.stack) Bantuan pada tumpukan fungsi di modul periksa:

stack (konteks = 1) Kembalikan daftar catatan untuk stack di atas bingkai pemanggil.

Saya merasa memang sangat membantu.


0

Dalam Python 3, pdb akan secara otomatis menginstal penangan sinyal saat pertama kali Anda menggunakan c (ont (inue)) di debugger. Menekan Control-C sesudahnya akan menjatuhkan Anda kembali ke sana. Dalam Python 2, berikut ini adalah satu-liner yang harus bekerja bahkan dalam versi yang relatif lama (diuji pada 2.7 tetapi saya memeriksa sumber Python kembali ke 2.4 dan terlihat oke):

import pdb, signal
signal.signal(signal.SIGINT, lambda sig, frame: pdb.Pdb().set_trace(frame))

pdb layak dipelajari jika Anda menghabiskan banyak waktu untuk debugging Python. Antarmuka agak tumpul tetapi harus akrab bagi siapa saja yang telah menggunakan alat serupa, seperti gdb.


0

Jika Anda perlu melakukan ini dengan uWSGI, ia memiliki built-in Python Tracebacker dan itu hanya masalah mengaktifkannya dalam konfigurasi (nomor terlampir pada nama untuk setiap pekerja):

py-tracebacker=/var/run/uwsgi/pytrace

Setelah selesai, Anda dapat mencetak jejak balik hanya dengan menghubungkan ke soket:

uwsgi --connect-and-read /var/run/uwsgi/pytrace1

0

Pada titik di mana kode dijalankan, Anda dapat memasukkan potongan kecil ini untuk melihat jejak tumpukan cetakan yang diformat dengan baik. Diasumsikan bahwa Anda memiliki folder yang dipanggil logsdi direktori root proyek Anda.

# DEBUG: START DEBUG -->
import traceback

with open('logs/stack-trace.log', 'w') as file:
    traceback.print_stack(file=file)
# DEBUG: END DEBUG --!
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.