IT

IPython을 사용한 단계별 디버깅

lottoking 2020. 6. 7. 10:10
반응형

IPython을 사용한 단계별 디버깅


내가 읽은 것에서 파이썬으로 코드를 디버깅하는 두 가지 방법이 있습니다.

  • 전통적인 디버거와 같은 pdbipdb. 등이 지원하는 명령 c에 대한 continue, n대한 step-over, s대한 step-into등),하지만 당신은 개체 검사에 매우 유용 할 수있는 IPython 쉘에 직접 액세스 할 수 없습니다.

  • 코드에 IPython 쉘 임베드 하여 IPython 사용 을 수행 한 다음 코드에서 사용할 수 있습니다. 프로그램 / 스크립트가 명령문에 도달하면 IPython 쉘에 빠지게됩니다. 이를 통해 모든 IPython 제품을 사용하여 객체를 완전히 검사하고 Python 코드를 테스트 할 수 있습니다. 그러나 사용 하면 편리한 키보드 단축키로 더 이상 코드를 단계별로 볼 수 없습니다 .from ipython import embedembed()embed()embed()

두 세계의 최고를 결합 할 수있는 방법이 있습니까?

  1. 할 수있을 단계별로 편리 PDB / ipdb 키보드 단축키를 사용하여 코드를 통해.
  2. 그러한 단계에서 (예 : 주어진 문장에서) 본격적인 IPython 쉘에 액세스 할 수 있습니다 .

MATLAB 에서와 같은 IPython 디버깅 :

이 유형의 "향상된 디버깅"의 예는 MATLAB에서 찾을 수 있으며, 여기서 사용자는 항상 MATLAB 엔진 / 쉘에 대한 전체 액세스 권한을 가지고 있으며 여전히 단계별 코드, 조건부 중단 점 정의 등을 수행 할 수 있습니다. 다른 사용자와 논의한 내용은 MATLAB에서 IPython으로 이동할 때 사람들이 가장 그리워하는 디버깅 기능입니다.

Emacs 및 기타 편집기에서 IPython 디버깅 :

질문을 너무 구체적으로 만들고 싶지는 않지만 대부분 Emacs에서 일하기 때문에이 기능을 가져올 수있는 방법이 있는지 궁금합니다. 이상적으로 는 Emacs (또는 에디터)는 프로그래머가 코드의 어느 곳에서든 중단 점을 설정하고 인터프리터 또는 디버거와 통신하여 선택한 위치에서 중지하고 해당 위치에서 완전한 IPython 인터프리터를 가져올 수 있도록합니다.


%pdb아직 IPython의 깃발을 언급 한 사람은 없습니다 . %pdbIPython에서 전화 하면 오류가 발생하면 자동으로 (으)로 이동 ipdb합니다. 당신은 즉시 스테핑을하지 않지만, 당신은 ipdb나중에 있습니다.

따라서 파일을로드 한 %load다음 함수를 실행할 수 있으므로 개별 함수를 쉽게 디버깅 할 수 있습니다 . assert올바른 위치에 오류가있을 수 있습니다.


ipdb.set_trace ()는 어떻습니까? 귀하의 코드에서 :

import ipdb; ipdb.set_trace()

업데이트 : 이제 Python 3.7에서 작성할 수 있습니다 breakpoint(). 동일하게 작동하지만 PYTHONBREAKPOINT환경 변수 도 준수 합니다. 이 기능은 이 PEP 에서 제공됩니다 .

이를 통해 코드를 완벽하게 검사 할 수 있으며 c(계속), n(다음 줄 실행), s(방법의 단계 ) 등의 명령에 액세스 할 수 있습니다 .

ipdb repo명령 목록을 참조하십시오 . IPython 은 이제 Jupyter 라고합니다 (편집 : 일부) .


추신 : ipdb 명령이 파이썬 코드보다 우선합니다. 따라서 글을 쓰 list(foo)려면 필요합니다 print list(foo).

또한 ipython 프롬프트 (emacs 및 vim 모드, 히스토리, 완료 등)가 마음에 들면 python prompt 툴킷을 기반으로하기 때문에 프로젝트에서 동일하게 쉽게 얻을 수 있습니다.


Emacs에서 RealGUD 사용 (2016 년 5 월 28 일 업데이트)

Emacs 사용자라면 누구나이 스레드 를 사용하여 OP (및 기타)에 설명 된 모든 것을 수행하는 방법을 보여줍니다.

  1. Emacs의 RealGUD 라는 새로운 중요한 디버거 는를 포함하여 모든 디버거와 함께 작동 할 수 있습니다 ipdb.
  2. 이맥스 패키지 isend-mode.

이 두 패키지의 조합은 매우 강력하며 OP에 설명 된 동작을 정확하게 재현하고 더 많은 작업을 수행 할 수 있습니다.

ipdb 용 RealGUD 위키 기사대한 추가 정보 .


원래 답변 :

이 스레드에서 언급 한 모든 것을 포함하여 Python을 디버깅하기 위해 다양한 방법을 시도한 후에 IPython으로 Python을 디버깅하는 가장 좋은 방법 중 하나는 임베디드 쉘입니다.

사용자 정의 임베디드 IPython 쉘 정의 :

PYTHONPATH메소드를 ipsh()사용할 수 있도록 스크립트에 다음을 추가하십시오 .

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)

그런 다음 코드에서 무언가를 디버깅 할 때마다 ipsh()객체 검사 등을 수행 해야하는 위치에 바로 배치 합니다. 예를 들어 my_function아래 에서 디버깅하고 싶다고 말하십시오.

그것을 사용 :

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

and then I invoke my_function(2) in one of the following ways:

  1. Either by running a Python program that invokes this function from a Unix shell
  2. Or by invoking it directly from IPython

Regardless of how I invoke it, the interpreter stops at the line that says ipsh(). Once you are done, you can do Ctrl-D and Python will resume execution (with any variable updates that you made). Note that, if you run the code from a regular IPython the IPython shell (case 2 above), the new IPython shell will be nested inside the one from which you invoked it, which is perfectly fine, but it's good to be aware of. Eitherway, once the interpreter stops on the location of ipsh, I can inspect the value of a (which be 2), see what functions and objects are defined, etc.

The problem:

The solution above can be used to have Python stop anywhere you want in your code, and then drop you into a fully-fledged IPython interpreter. Unfortunately it does not let you add or remove breakpoints once you invoke the script, which is highly frustrating. In my opinion, this is the only thing that is preventing IPython from becoming a great debugging tool for Python.

The best you can do for now:

A workaround is to place ipsh() a priori at the different locations where you want the Python interpreter to launch an IPython shell (i.e. a breakpoint). You can then "jump" between different pre-defined, hard-coded "breakpoints" with Ctrl-D, which would exit the current embedded IPython shell and stop again whenever the interpreter hits the next call to ipsh().

If you go this route, one way to exit "debugging mode" and ignore all subsequent breakpoints, is to use ipshell.dummy_mode = True which will make Python ignore any subsequent instantiations of the ipshell object that we created above.


You can start IPython session from pudb and go back to the debugging session as you like.

BTW, ipdb is using IPython behind the scenes and you can actually use IPython functionality such as TAB completion and magic commands (the one starts with %). If you are OK with ipdb you can start it from IPython using commands such as %run and %debug. ipdb session is actually better than plain IPython one in the sense you can go up and down in the stack trace etc. What is missing in ipdb for "object inspection"?

Also, python.el bundled with Emacs >= 24.3 has nice ipdb support.


Looks like the approach in @gaborous's answer is deprecated.

The new approach seems to be:

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

def buggy_method():
    debug()

Prefixing an "!" symbol to commands you type in pdb seems to have the same effect as doing something in an IPython shell. This works for accessing help for a certain function, or even variable names. Maybe this will help you to some extent. For example,

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

But !help(numpy.transpose) will give you the expected help page on numpy.transpose. Similarly for variable names, say you have a variable l, typing "l" in pdb lists the code, but !l prints the value of l.


Did you try this tip?

Or better still, use ipython, and call:

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

then you can just use

debug_here()

whenever you want to set a breakpoint


One option is to use an IDE like Spyder which should allow you to interact with your code while debugging (using an IPython console, in fact). In fact, Spyder is very MATLAB-like, which I presume was intentional. That includes variable inspectors, variable editing, built-in access to documentation, etc.


the right, easy, cool, exact answer for the question is to use %run macro with -d flag.

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

If you type exit() in embed() console the code continue and go to the next embed() line.


The Pyzo IDE has similar capabilities as the OP asked for. You don't have to start in debug mode. Similarly to MATLAB, the commands are executed in the shell. When you set up a break-point in some source code line, the IDE stops the execution there and you can debug and issue regular IPython commands as well.

It does seem however that step-into doesn't (yet?) work well (i.e. stopping in one line and then stepping into another function) unless you set up another break-point.

Still, coming from MATLAB, this seems the best solution I've found.


Running from inside Emacs' IPython-shell and breakpoint set via pdb.set_trace() should work.

Checked with python-mode.el, M-x ipython RET etc.


From python 3.2, you have the interact command, which gives you access to the full python/ipython command space.


Not explicitly said before is that you can call IPython.embed() from within ipdb.

ipdb is great for stepping through code and for itrospection, but it doesn't handle other things, like multiple lines, well. IPython handles multi-line statements well.

To induce the debugger, call the following in your code:

import idpb; ipdb.set_trace()

This allows for introspection and stepping.

If you need IPython functionality, call the following in ipdb>:

from IPython import embed; embed()

Regarding Emacs, here's my idiosyncratic solution which I hope inspires you.

I use Emacs with M-x shell. I have a yassnippet defined for ipdb which induces the debugger. The bm package highlights the line so that I don't forget to remove it from the source code:

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

I import IPython in my .pdbrc file:

try:
    from IPython import embed
except:
    pass

This allows me to call embed() from any ipdb instance (when IPython is installed).

참고URL : https://stackoverflow.com/questions/16867347/step-by-step-debugging-with-ipython

반응형