본문 바로가기

Develop

python 디버깅 툴, pdb

코딩은 즐거움이다. 머리속에 있던 생각을 실행이 되는 구체화된 결과물을 만들어 내는 과정이기 때문이다. 또 결과물이 내가 의도했던대로 무리없이 작동하면 보람도 느낀다. 그 과정속에 어려움도 있다. 기대했던 바대로 작동하지 않는 경우가 비일비재해서다. 그리고 대부분 그러한 경우 원인을 쉽게 찾기 어렵다. 간단히 print() 를 사용할 수 있지만 좀더 진보된 툴, pdb를 써보자.

아래의 예는 django에서 ipdb(Improved pdb)를 사용한 예이다.

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        import ipdb; ipdb.set_trace()
        return Question.objects.filter(
            pub_date__lte=timezone.now()
        ).order_by('-pub_date')[:5]

위와 같이 관심있는 줄에 import ipdb; ipdb.set_trace() 추가하자.

그러면 실행흐름이 위 코드에 닿을 때, 실행을 멈추게 되고 개발자의 입력을 대기하는 prompt 가 나타난다.


System check identified no issues (0 silenced).
January 24, 2021 - 10:08:19
Django version 3.1.4, using settings 'mysite.settings'
Starting development server at http://0:8000/
Quit the server with CONTROL-C.
> /home/hm_home/work/anything/django-polls/polls/views.py(20)get_queryset()
     19         import ipdb; ipdb.set_trace()
---> 20         return Question.objects.filter(
     21             pub_date__lte=timezone.now()

앞뒤 문맥을 확인하기 위해 확인차 list를 실행해본다.


ipdb> list
     15         """
     16         Return the last five published questions (not including those set to be
     17         published in the future).
     18         """
     19         import ipdb; ipdb.set_trace()
---> 20         return Question.objects.filter(
     21             pub_date__lte=timezone.now()
     22         ).order_by('-pub_date')[:5]
     23 
     24 
     25 class DetailView(generic.DetailView):

마치 python shell과 같은 상태이므로 실행가능한, 연산가능한 모든 수식을 실행해 볼 수 있다.

ipdb> print(Question)
<class 'polls.models.Question'>
ipdb> Question.objects.all()
<QuerySet [<Question: 좋아하는 색은?>, <Question: 좋아하는 국가는?>]>
ipdb> for ques in Question.objects.all(): print(ques)
좋아하는 색은?
좋아하는 국가는?
ipdb> for ques in Question.objects.all(): print(ques, ques.id)
좋아하는 색은? 3
좋아하는 국가는? 4

한 줄만 실행해보고 싶다면 n(next)를 입력한다. 그러면 실행줄이 20에서 21로 변환이 된다. 개발자가 원하는 만큼 실행하며 문맥의 값을 확인해 볼 수 있다.

ipdb> n
> /home/hm_home/work/anything/django-polls/polls/views.py(21)get_queryset()
     20         return Question.objects.filter(
---> 21             pub_date__lte=timezone.now()
     22         ).order_by('-pub_date')[:5]

충분한 분석이 마무리 되었다면 실행흐름을 놓아주자. n 과 달리 c(continue)를 입력하면 다음 break point를 만날 때까지 실행이 된다.

ipdb> c
[24/Jan/2021 10:09:05] "GET /polls/ HTTP/1.1" 200 237

더이상 디버깅이 필요 없다면 추가했던 ipdb라인을 삭제해야 한다.

불필요한 코드를 추가하는 번거로운 작업으로 느껴 질 수 있다. 의심되는 곳에 print() 문을 추가하는 것과 비교하면 좀더 효율적인 과정이지 않을까.

 

 

appletree.or.kr/quick_reference_cards/Python/Python%20Debugger%20Cheatsheet.pdf

반응형