IPython ile adım adım hata ayıklama


170

Ne okudum, Python kodu hata ayıklamak için iki yolu vardır:

  • pdbVeya gibi geleneksel bir hata ayıklayıcı ile ipdb. Gibi bu destekler komutlar ciçin continue, niçin step-over, siçin step-intovb), ancak nesne kontrolü için son derece yararlı olabilir bir ipython kabuğuna doğrudan erişim yok.

  • Kullanarak IPython tarafından katıştırma kodunuzda bir ipython kabuk. Yapabilir from ipython import embedve daha sonra embed()kodunuzda kullanabilirsiniz . Programınız / komut dosyanız bir embed()deyime çarptığında , bir IPython kabuğuna bırakılırsınız. Bu, tüm IPython özelliklerini kullanarak nesnelerin tam olarak incelenmesine ve Python kodunun test edilmesine izin verir. Kullanırken Ancak, embed()sen olamaz adım adım kodu ile artık kullanışlı klavye kısayolları ile.

Her iki dünyanın en iyilerini birleştirmenin bir yolu var mı? yani

  1. Muktedir adım-adım kullanışlı pdb / ipdb klavye kısayolları ile kod üzerinden.
  2. Böyle bir adımda (örneğin, belirli bir ifadede), tam teşekküllü bir IPython kabuğuna erişebilirsiniz .

MATLAB'daki gibi IPython hata ayıklaması :

Bu tür bir "gelişmiş hata ayıklama" örneği, kullanıcının her zaman MATLAB motoruna / kabuğuna tam erişime sahip olduğu ve koduyla adım adım ilerleyebildiği, koşullu kesme noktalarını tanımlayabileceği MATLAB'da bulunabilir . diğer kullanıcılarla tartıştığım, bu MATLAB'dan IPython'a geçerken insanların en çok özledikleri hata ayıklama özelliğidir.

Emacs ve diğer editörlerde IPython hata ayıklama:

Soruyu fazla özelleştirmek istemiyorum, ama çoğunlukla Emacs'ta çalışıyorum, bu yüzden bu işlevselliği içine sokmanın herhangi bir yolu olup olmadığını merak ediyorum. İdeal olarak , Emacs (veya editör), programlayıcının kodun herhangi bir yerinde kesme noktaları ayarlamasına ve seçtiğiniz konumda durması için yorumlayıcı veya hata ayıklayıcı ile iletişim kurmasına ve bu konumdaki tam bir IPython yorumlayıcısına ulaşmasına izin verir.


pdb, !kesme noktasında herhangi bir python komutunu yürüten komuta sahiptir
Dmitry Galchinsky

5
Ben de Matlab benzer bir python hata ayıklayıcı arıyorum! Örneğin, python kabuğunda çok fazla prototipleme yapıyorum. Tüm değişkenler kabuk ile kaydedilir. Şimdi bir sorunla karşılaşıyorum. Ben küçük bir kod parçası, bu hesaplanan değişkenler kabuk ile hata ayıklamak istiyoruz. Ancak, yeni bir hata ayıklayıcı eski değişkenlere erişemez. Prototipleme için uygun değildir.
user1914692

1
Emacs kullanıcıları için RealGUD inanılmaz derecede iyi bir arayüze sahiptir.
Clément

1
Teşekkürler @ Clément Geçen ay repoyu takip ediyorum ve proje hakkında çok heyecanlıyım :) Henüz denemedim, ama bir kez (ya da yaparsanız) belki burada bir cevap yazmaktan çekinmeyin istenenleri nasıl gerçekleştireceğinizi gösterir. Referans olarak başkaları için URL github.com/rocky/emacs-dbgr
Amelio Vazquez-Reina

@ Clément Ayrıca, RealGUD & ipdb ile herhangi bir deneyiminiz varsa, burada açıklandığı gibi kullanmayı denedim github.com/rocky/emacs-dbgr/issues/96 şanssız.
Amelio Vazquez-Reina

Yanıtlar:


61

IPython'un %pdbbüyüsünü kullanabilirsiniz . Sadece %pdbIPython'u arayın ve bir hata oluştuğunda otomatik olarak iptal edilirsiniz ipdb. Hemen adım atmasanız da,ipdb daha sonra içeri girersiniz.

Bu, tek tek işlevlerde hata ayıklamayı kolaylaştırır, çünkü sadece bir dosyayı yükleyip %loadbir işlevi çalıştırabilirsiniz. İle ilgili bir hatayı zorlayabilirsinizassertDoğru konumda .

%pdbbir çizgi büyüsü. Olarak çağır %pdb on, %pdb 1, %pdb offveya %pdb 0. Bağımsız değişken olmadan çağrılırsa, bir geçiş işlevi görür.


6
^ Bu gerçek cevap
Cesar

Pdb başlangıçta IPython olmadan IPython benzeri işlevsellik var benzer bir şey var mı?
Lucas

4
Ayrıca programı başlatabilir ve ipython --pdb file.py -- argsbir istisna üzerine ipdb'ye bırakabilirsiniz. Cevaba eklemeye değer olabilir.
sebastian

110

İpdb.set_trace () hakkında ne? Kodunuzda:

import ipdb; ipdb.set_trace()

güncelleme : şimdi Python 3.7, yazabiliriz breakpoint(). Aynı şekilde çalışır, ancak PYTHONBREAKPOINTortam değişkenine de uyar . Bu özellik bu PEP'ten geliyor .

Bu, kodunuzun tam olarak incelenmesine olanak tanır ve c(devam), n(sonraki satırı yürüt), s(noktadaki yönteme adım atma) ve benzeri komutlara erişebilirsiniz .

İpdb repo'ya ve komutların listesine bakın . IPython artık Jupyter olarak adlandırılıyor (değiştir: parçası) .


ps: bir ipdb komutunun python koduna göre öncelikli olduğuna dikkat edin. Yani yazmak list(foo)için ihtiyacınız olacak print list(foo).

Ayrıca, ipython istemini (emacs ve vim modları, geçmişi, tamamlamaları, ...) beğendiyseniz, python istemi araç setine dayandığı için projeniz için aynı şeyi almak kolaydır .


10
Bunu yapmanın yolu bu.
j08lue

Cevabım şimdi ipdbEmacs'ta OP'nin istediklerini kullanarak RealGUDve isend-modetam olarak ne yapacağını içeriyor .
Amelio Vazquez-Reina

1
Jupyter IPython'un yerine IPython Notebook'un yerine geçer. Jupyter dizüstü bilgisayarlar arka planda çekirdek kullanır. Python dizüstü bilgisayar için, çekirdek genellikle bir IPython çekirdeğidir. İpython projesi ayrıca devam ediyor.
FA

1
breakpoint()harika. PyCharm'da sizi PyCharm hata ayıklayıcısına bile bırakır. Ayrıca, konsola yapıştırılan işlevlerden PyCharm hata ayıklayıcısına girmenin hızlı bir yoludur.
Richard Möhn

40

(28 Mayıs 2016'da Güncelleme) Emacs'ta RealGUD Kullanımı

Emacs'taki herkes için bu iş parçacığı OP (ve diğer) öğesinde açıklanan her şeyin nasıl kullanılacağını gösterir.

  1. Emacs'ta RealGUD adı verilen ve herhangi bir hata ayıklayıcı ile çalışabilecek yeni bir önemli hata ayıklayıcı (ipdb ) .
  2. Emacs paketi isend-mode.

Bu iki paketin kombinasyonu son derece güçlüdür ve OP'de açıklanan davranışı tam olarak yeniden oluşturmasına ve daha fazlasını yapmasına izin verir.

İpdb için RealGUD'un wiki makalesi hakkında daha fazla bilgi .


Orijinal cevap:

Python'da hata ayıklamak için birçok farklı yöntem denedikten sonra, bu iş parçacığında bahsedilen her şey dahil, Python'u IPython ile hata ayıklamak için tercih ettiğim yollardan biri gömülü kabuklarla.

Özel bir katıştırılmış IPython kabuğu tanımlama:

PYTHONPATHYöntemin ipsh()kullanılabilir olması için aşağıdakine komut dosyasında ekleyin .

import inspect

# First import the embed function
from IPython.terminal.embed import InteractiveShellEmbed
from IPython.config.loader import Config

# Configure the prompt so that I know I am in a nested (embedded) shell
cfg = Config()
prompt_config = cfg.PromptManager
prompt_config.in_template = 'N.In <\\#>: '
prompt_config.in2_template = '   .\\D.: '
prompt_config.out_template = 'N.Out<\\#>: '

# Messages displayed when I drop into and exit the shell.
banner_msg = ("\n**Nested Interpreter:\n"
"Hit Ctrl-D to exit interpreter and continue program.\n"
"Note that if you use %kill_embedded, you can fully deactivate\n"
"This embedded instance so it will never turn on again")   
exit_msg = '**Leaving Nested interpreter'

# Wrap it in a function that gives me more context:
def ipsh():
    ipshell = InteractiveShellEmbed(config=cfg, banner1=banner_msg, exit_msg=exit_msg)

    frame = inspect.currentframe().f_back
    msg   = 'Stopped at {0.f_code.co_filename} at line {0.f_lineno}'.format(frame)

    # Go back one level! 
    # This is needed because the call to ipshell is inside the function ipsh()
    ipshell(msg,stack_depth=2)

Daha sonra, kodumda bir şey hata ayıklamak istediğimde, ipsh()nesne denetimi vb. Yapmam gereken yere yerleştiriyorum. Örneğin, hata ayıklamak istediğimi söyleyinmy_function aşağıda

Kullanma:

def my_function(b):
  a = b
  ipsh() # <- This will embed a full-fledged IPython interpreter
  a = 4

ve sonra my_function(2)aşağıdaki yollardan biriyle çağırıyorum :

  1. Bu işlevi bir Unix kabuğundan çağıran bir Python programı çalıştırarak
  2. Veya doğrudan IPython'dan çağırarak

Nasıl çağırdığımdan bağımsız olarak, tercüman söyleyen satırda durur ipsh(). İşiniz bittiğinde, bunu yapabilirsiniz Ctrl-Dve Python yürütmeye devam eder (yaptığınız değişken güncellemelerle). Eğer (olgu yukarıdaki 2) düzenli ipython ipython kabuk kodunu çalıştırırsanız, unutmayın, yeni ipython kabuk edilecektir yuvalanmış gayet olumlu bunu çağrılan hangi birine içeride, ama onun iyi farkında olmak. Her iki durumda da, tercüman bulunduğu yerde durduğunda, (ki ) ipshdeğerini inceleyebilir, hangi işlevlerin ve nesnelerin tanımlandığını vb. Görebilirim.a2

Sorun:

Yukarıdaki çözüm, Python'un kodunuzda istediğiniz yerde durmasını ve ardından sizi tam teşekküllü bir IPython yorumlayıcısına bırakmasını sağlamak için kullanılabilir. Ne yazık ki son derece sinir bozucu olan komut dosyasını çağırdıktan sonra kesme noktaları eklemenize veya kaldırmanıza izin vermez. Bence, IPython'un Python için harika bir hata ayıklama aracı olmasını engelleyen tek şey bu.

Şimdilik yapabileceğiniz en iyi şey:

Geçici çözüm, ipsh()Python yorumlayıcısının bir IPython kabuğu (ör. A breakpoint) başlatmasını istediğiniz farklı konumlara bir a priori yerleştirmektir . Ardından, önceden tanımlanmış farklı sabit kodlu "kesme noktaları" arasında "atlayabilir" Ctrl-Dve bu, geçerli katıştırılmış IPython kabuğundan çıkıp yorumlayıcı bir sonraki çağrıya her bastığında yeniden durabilir ipsh().

Bu rotaya giderseniz, "hata ayıklama modundan" çıkmanın ve sonraki tüm kesme noktalarını göz ardı etmenin bir yolu, ipshell.dummy_mode = TruePython'un ipshellyukarıda oluşturduğumuz nesnenin sonraki örneklerini yok saymasını sağlayacak şekilde kullanmaktır .


2
Daha da iyi bir çözüm bulduğunuzda lütfen bunu güncelleyin. Ama bu harika görünüyor. Kullanacağım.
Phani

1
Cfg, banner_msg, exit_msg'yi nerede / nasıl tanımlar ve içe aktarırsınız?
Gordon Bean

1
Bu benim için iyi çalışıyor gibi görünüyor: github.com/kdodia/snippets/blob/master/ipsh.py
karan.dodia

1
Çalışmadan import inspectönce eklemem gerekiyordu . Komut satırı özelleştirmesi benim için kırılmış gibi görünüyor.
Pascal

7
Neden sadece kullanmıyorsunuz import ipdb; ipdb.set_trace()? Belki bir şeyi özlüyorum, ama çok daha karmaşık yönteminizin avantajını görmüyorum.
luator

19

IPython oturumunu pudb'dan başlatabilir ve istediğiniz şekilde hata ayıklama oturumuna geri dönebilirsiniz.

BTW, ipdb, sahne arkasında IPython kullanıyor ve aslında TAB tamamlama ve sihirli komutlar (biriyle başlıyor %) gibi IPython işlevselliğini kullanabilirsiniz . İpdb ile sorun yaşıyorsanız %runve gibi komutları kullanarak IPython'dan başlatabilirsiniz %debug. ipdb oturumu aslında yığın izleme vb yukarı ve aşağı gidebilirsiniz anlamında düz IPython bir iyidir. "Nesne denetimi" için ipdb eksik nedir?

Ayrıca, Emacs> = 24.3 ile birlikte gelen python.el güzel ipdb desteğine sahiptir.


1
Teşekkürler tkf. Emacs-Jedi paketinizin büyük hayranıyım. Emacs 24.3'ün ipdb için güzel bir desteği olduğunu söylediğinizde, özenle düşünür müsünüz? IPython'u genellikle ayrı bir M-x ansi-termarabellekte başlatırım ve sonra IPython arabelleğine otomatik olarak sihir gönderen bir klavye kısayolu ile IPython yorumlayıcısına kod gönderebilmem için kaynak tamponlarımı IPython arabelleğine bağlamak için isend-modunu kullanırım %paste. Bu, IPython'daki bölgeleri hızlı bir şekilde test etmeme izin veriyor. Programlarımı her zaman bu IPython kabuğundan çalıştırıyorum runve embed()durdurmak için kullanıyorum.
Amelio Vazquez-Reina

3
Örneğin, kod içinde adım attığınızda, kaynak kod diğer arabellekte ok geçerli yürütme noktasını gösterecek şekilde açılır. Ayrıca isend-mode'da yaptığınız gibi gönderme bölgesi komutunuz da var.
tkf

Thanks @tkf Nasıl ipdbhata ayıklama oturumu kullanarak python.elve send-regionilgili kabuk vb gibi şeyler var ? Genel olarak, bu konuda daha fazla bilgiyi nerede bulabilirim?
Amelio Vazquez-Reina

Kullandığım %runveya %debug. Sanırım da import ipdb; ipdb.set_trace()işe yarıyor. Ben ipdb birden fazla satır gönderebilirsiniz sanmıyorum. Bu ipdb'nin sınırlamasıdır. Ama muhtemelen %pastehile çalışır. IPython geliştiricisine bir özellik isteği göndermek isteyebilirsiniz.
tkf

13

Görünüşe göre @ gaborous'un cevabındaki yaklaşım reddedildi .

Yeni yaklaşım şöyledir:

from IPython.core import debugger
debug = debugger.Pdb().set_trace

def buggy_method():
    debug()

Bu ipdb, hata ayıklama sırasında ipython kabuğu içinde ifadeler kullanmanıza izin veriyor mu?
alpha_989

6

Bir "!" pdb'de yazdığınız komutların sembolü, IPython kabuğunda bir şey yapmakla aynı etkiye sahip gibi görünüyor. Bu, belirli bir işlev veya hatta değişken adları için yardıma erişmek için çalışır. Belki bu size bir ölçüde yardımcı olacaktır. Örneğin,

ipdb> help(numpy.transpose)
*** No help on (numpy.transpose)

Ancak! Help (numpy.transpose) size numpy.transpose ile ilgili beklenen yardım sayfasını verecektir. Benzer şekilde, değişken adları için, d değişkenine sahip olduğunuzu varsayalım, pdb'ye "l" yazdığınızda kod listelenir, ancak! L l değerini yazdırır.


2
Bu kötü bir pdb gotcha ve iyi bilmeye değer.
Wilfred Hughes

4

Bu ipucunu denedin mi?

Ya da daha iyisi, ipython kullanın ve şunu arayın:

from IPython.Debugger import Tracer; debug_here = Tracer()

o zaman kullanabilirsiniz

debug_here()

bir kesme noktası ayarlamak istediğinizde


4

Sen başlayabilirsiniz IPython içinden ipdb !

ipdbHata ayıklayıcı 1'i başlatın :

import idpb; ipdb.set_trace()

IPython Enter içinden de ipdb>konsolun 2 :

from IPython import embed; embed()

İçeriden ipdb>konsola dön IPython:

exit

Emacs kullanmak için yeterince şanslıysanız, işler daha da kolay hale getirilebilir!

Bunun için kullanılması gerekir M-x shell. yasnippetVe bm tuşlarını kullanarak aşağıdaki snippet'i tanımlayın. Bu ipdb, editördeki metni set-tracesatırla değiştirir. Parçacığı yerleştirdikten sonra, çizgi kolayca fark edilir ve gezinilebilir şekilde vurgulanır. M-x bm-nextGezinmek için kullanın .

# -*- mode: snippet -*-
# name: ipdb
# key: ipdb
# expand-env: ((yas-after-exit-snippet-hook #'bm-toggle))
# --
import ipdb; ipdb.set_trace()

1 Kolay silme için hepsi bir satırda. Beri importssadece bu formu olmasını sağlar, bir kez gerçekleşmesi ipdbhiçbir ekstra yükü ile ihtiyacınız olduğunda ithal edilecektir.

2 Sen içe kendinize biraz yazarak kaydedebilirsiniz IPython senin içinde .pdbrcdosyaya :

try:
    from IPython import embed
except:
    pass

Bu, embed()içinden kolayca arama yapmanızı sağlar ipdb(elbette, yalnızca IPython yüklü olduğunda).


3

Bir seçenek, hata ayıklama sırasında (aslında bir IPython konsolu kullanarak) kodunuzla etkileşime girmenizi sağlayan Spyder gibi bir IDE kullanmaktır . Aslında, Spyder kasıtlı olduğunu düşündüğüm MATLAB benzeri. Buna değişken denetçiler, değişken düzenleme, belgelere yerleşik erişim vb. Dahildir.


3

soru için doğru, kolay, havalı, kesin cevap% run makrosunu -d bayrağı ile kullanmaktır.

In [4]: run -d myscript.py
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.        
> /cygdrive/c/Users/mycodefolder/myscript.py(4)<module>()
      2                                                            
      3                        
----> 4 a=1                                            
      5 b=2

Bu daha yüksek olmalı. Koduma (modül içinde) bir satır eklemem gerekirse, modülü yeniden yüklemek için IPython'u yeniden başlatmam gerekir. Bu ile, ben sadece %save /tmp/foo.py x-yçalıştırmak ve hata ayıklamak istiyorum kod ve sonra %run -d /tmp/foo.pyistediğim yerde kesme noktası ayarlamak için. Mükemmel cevap!
Romeo Valentin

2

Embed () konsoluna exit () yazarsanız kod devam eder ve sonraki embed () satırına gider.


2

Pyzo IDE OP istedi gibi benzer yeteneklere sahiptir. Hata ayıklama modunda başlamak zorunda değilsiniz. MATLAB'a benzer şekilde, komutlar kabukta yürütülür. Bazı kaynak kodu satırında bir kesme noktası ayarladığınızda, IDE burada yürütmeyi durdurur ve hata ayıklama yapabilir ve normal IPython komutlarını da verebilirsiniz.

Bununla birlikte, başka bir kırılma noktası ayarlamadığınız sürece adım adım (henüz?) İyi çalışmaz (yani bir satırda durup başka bir işleve adım atma).

Yine de, MATLAB'dan gelen bu, bulduğum en iyi çözüm gibi görünüyor.


2

Python 3.2'den, interacttam python / ipython komut alanına erişmenizi sağlayan bir komuta sahipsiniz.


1

Emacs'ın içinden çalışan pytb.set_trace () ile belirlenen IPython kabuğu ve kesme noktası çalışmalıdır.

Python-mode.el, Mx ipython RET vb.


1

Yeni Kod Geliştirme

IPython içinde hata ayıklama

  1. Deneme yinelemelerini hızlandırmak için Jupyter / IPython hücre yürütülmesini kullanma
  2. Adım adım ilerlemek için %% hata ayıklama kullanın

Hücre Örneği:

%%debug
...: for n in range(4):
...:    n>2

Mevcut Kodda Hata Ayıklama

IPython içinde hata ayıklama

  1. Bozuk birim testinde hata ayıklama: pytest ... --pdbcls=IPython.terminal.debugger:TerminalPdb --pdb
  2. Test durumda dışında ayıklama: breakpoint(), python -m ipdbvb
  3. Hata ayıklayıcıdayken gereken yerlerde tam IPython işlevselliği için IPython.embed ()

Python Üzerine Düşünceler

OP ile MATLAB'ın Python'un hala sahip olmadığı ve gerçekten olması gereken pek çok şey olduğu konusunda hemfikirim çünkü dilde hemen hemen her şey üretim hızına göre geliştirme hızını destekliyor. Belki bir gün CPython'a önemsiz hata düzeltmelerinden daha fazla katkıda bulunacağım.

https://github.com/ipython/ipython/commit/f042f3fea7560afcb518a1940daa46a72fbcfa68

Ayrıca bkz . IPython'da hata ayıklama ile komut çalıştırmak mümkün mü?

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.