pdb를 이용해 python 코드를 디버깅하는 방법을 알아보자.


환경

  • Linux 기반 시스템
  • Bash shell(/bin/bash)
  • Python


pdb

pdb란?

  • pdb : 파이썬 디버깅 도구로 파인썬 인터프리터를 줄마다 보면서 실행할 수 있도록 도와주는 도구입니다.


실행 방법

pdb 실행방법 - 1

  • 처음부터 코드를 실행할 때 사용
python3 -m pdb example.py
  • 실행 예제
$ python -m pdb test.py
> /Users/taewoo/test.py(1)<module>()
-> def test_sum(a,b):
(Pdb)

pdb 실행방법 - 2

  • 코드의 특정 부분부터 사용
# In python code
...
import pdb; pdb.set_trace()
...
  • 실행 예제
$ python test.py
> /Users/taewoo/test.py(6)<module>()
-> b=30
(Pdb)


사용법

사용 명령어 목록

  • l : 주변 소스코드들을 출력하며 현재 라인이 화살표로 나옵니다.
  • n : 다음 문장으로 이동합니다. 즉, 위에 l에서 위치한 부분을 실행하고 다음 명령어줄로 가는겁니다.
  • s : 흔히 사용하는 ‘Step Into’로 함수 내부로 들어갑니다. --Call--이라고 나오며 다 진행된 후에는 --Return--이 나옵니다.
  • c : 다음줄부터 중단점을 만날때까지 코드를 실행하며 중단점이 없다면 끝까지 실행합니다.
  • r : 현재 함수의 return이 나올때까지 실행합니다.
  • w : 함수의 call stack을 보여줍니다.
  • cl : 모든 중단점들을 삭제합니다.
  • b : 특정파일이나 패키지의 줄번호나 함수명으로 중단점을 만들 수 있습니다.
  • a : 현재 함수의 매개변수들을 출력.

사용 명령어 예제

  • l : 주변 소스코드들을 출력하며 현재 라인이 화살표로 나옵니다.
(Pdb) l
  1  	def test_sum(a,b):
  2  	    return a+b
  3
  4  	a=10
  5  ->	b=30
  6  	c=test_sum(a,b)
  7
  8  	for i in range(1,10):
  9  	    a = a + i
 10
 11  	import requests
  • n : 다음 문장으로 이동합니다. 즉, 위에 l에서 위치한 부분을 실행하고 다음 명령어줄로 가는겁니다.
(Pdb)  n
> /Users/taewoo/test.py(6)<module>()
-> c=test_sum(a,b)
  • s : 흔히 사용하는 ‘Step Into’로 함수 내부로 들어갑니다. --Call--이라고 나오며 다 진행된 후에는 --Return--이 나옵니다.
(Pdb)  s
--Call--
> /Users/taewoo/test.py(1)test_sum()
-> def test_sum(a,b):
...
--Return--
> /Users/taewoo/test.py(5)test_sum()->40
-> return a+b
  • c : 다음줄부터 중단점을 만날때까지 코드를 실행하며 중단점이 없다면 끝까지 실행합니다.
(Pdb) c
The program finished and will be restarted
  • r : 현재 함수의 return이 나올때까지 실행합니다.
(Pdb) s
--Call--
> /Users/taewoo/test.py(1)test_sum()
-> def test_sum(a,b):
(Pdb) r
--Return--
> /Users/taewoo/test.py(5)test_sum()->40
-> return a+b
  • w : 함수의 call stack을 보여줍니다.
(Pdb) w
  /Users/taewoo/.pyenv/versions/3.6.2/lib/python3.6/bdb.py(431)run()
-> exec(cmd, globals, locals)
  <string>(1)<module>()
  /Users/taewoo/test.py(9)<module>()
-> c=test_sum(a,b)
> /Users/taewoo/test.py(5)test_sum()->40
-> return a+b
  • cl : 모든 중단점들을 삭제합니다.
(Pdb) cl
Clear all breaks? y
  • b : 특정파일이나 패키지의 줄번호나 함수명으로 중단점을 만들 수 있습니다.
(Pdb) b 8
Breakpoint 1 at /Users/taewoo/test.py:8
(Pdb) b test_sum
Breakpoint 2 at /Users/taewoo/test.py:1
# Stop at line number 8
(Pdb) c
> /Users/taewoo/test.py(8)<module>()
-> b=30
# Stop at function
(Pdb) c
> /Users/taewoo/test.py(2)test_sum()
-> tmp=1
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/taewoo/test.py:8
	breakpoint already hit 2 times
2   breakpoint   keep yes   at /Users/taewoo/test.py:1
	breakpoint already hit 1 time
  • a : 현재 함수의 매개변수들을 출력.
(Pdb)  s
--Call--
> /Users/taewoo/test.py(1)test_sum()
-> def test_sum(a,b):
(Pdb) a
a = 10
b = 30

기타

  • 변수 값을 확인하고 싶을때 해당 변수를 명령어처럼 입력하던가 print함수를 이용할 수 있습니다.
(Pdb) c
> /Users/taewoo/test.py(2)test_sum()
-> tmp=1
(Pdb) n
> /Users/taewoo/test.py(3)test_sum()
-> tmp=2
(Pdb) tmp
1
(Pdb) print(tmp)
1
(Pdb) type(data)
<class 'dict'>
(Pdb) data
{'data': [{'type': 'articles', 'id': '1', 'attributes': {'title': 'JSON API paints my bikeshed!', 'body': 'The shortest article. Ever.', 'created': '2015-05-22T14:56:29.000Z', 'updated': '2015-05-22T14:56:28.000Z'}, 'relationships': {'author': {'data': {'id': '42', 'type': 'people'}}}}], 'included': [{'type': 'people', 'id': '42', 'attributes': {'name': 'John', 'age': 80, 'gender': 'male'}}]}
  • 코드 상에 중단점 추가하기
  • 코드 중간에 import pdb; pdb.set_trace()를 추가하면 해당 부분에서 멈춥니다.
def test_sum(a,b):
    tmp=1
    tmp=2
    tmp=3
    return a+b

a=10
b=30
c=test_sum(a,b)

for i in range(1,10):
    a = a + i

import requests
import pdb; pdb.set_trace()
url = 'https://gist.githubusercontent.com/TWpower/771f9dfc8d9e1ddc0ecbdaea5b2e379e/raw/2c7785b4835138255bdadb71bd83702e53ac2677/test-example.json'

data = requests.get(url).json()
$ python -m pdb test.py
> /Users/taewoo/test.py(1)<module>()
-> def test_sum(a,b):
(Pdb) c
> /Users/taewoo/test.py(16)<module>()
-> url = 'https://gist.githubusercontent.com/TWpower/771f9dfc8d9e1ddc0ecbdaea5b2e379e/raw/2c7785b4835138255bdadb71bd83702e53ac2677/test-example.json'
(Pdb)


참고자료

Debug python code using pdb.


Environment and Prerequisite

  • Linux base system
  • Bash shell(/bin/bash)
  • Python


pdb

What is pdb?

  • pdb : Interactive source code debugger for Python programs.


How to run

pdb run method - 1

  • Run pdb in start time.
python3 -m pdb example.py
  • Run example
$ python -m pdb test.py
> /Users/taewoo/test.py(1)<module>()
-> def test_sum(a,b):
(Pdb)

pdb run method - 2

  • Add to code
# In python code
...
import pdb; pdb.set_trace()
...
  • Run example
$ python test.py
> /Users/taewoo/test.py(6)<module>()
-> b=30
(Pdb)


Usage

Usage command list

  • l : Print codes of around current point. Current point will be marked by arrow.
  • n : Move to next statement. In other words, run statement which is shown in above l command’s arrow and move to next statement.
  • s : Commonly used ‘Step Into’ command. --Call-- will be shown after stepped in and --Return-- will be shown after return.
  • c : Run codes until meet next break point.
  • r : Run command until meet return.
  • w : Show current call stack.
  • cl : Clear all break points.
  • b : Make break point to file’s or package’s specific function or line.
  • a : Print function’s all arguments.

Usage command example

  • l : Print codes of around current point. Current point will be marked by arrow.
(Pdb) l
  1  	def test_sum(a,b):
  2  	    return a+b
  3
  4  	a=10
  5  ->	b=30
  6  	c=test_sum(a,b)
  7
  8  	for i in range(1,10):
  9  	    a = a + i
 10
 11  	import requests
  • n : Move to next statement. In other words, run statement which is shown in above l command’s arrow and move to next statement.
(Pdb)  n
> /Users/taewoo/test.py(6)<module>()
-> c=test_sum(a,b)
  • s : Commonly used ‘Step Into’ command. --Call-- will be shown after stepped in and --Return-- will be shown after return.
(Pdb)  s
--Call--
> /Users/taewoo/test.py(1)test_sum()
-> def test_sum(a,b):
...
--Return--
> /Users/taewoo/test.py(5)test_sum()->40
-> return a+b
  • c : Run codes until meet next break point.
(Pdb) c
The program finished and will be restarted
  • r : Run command until meet return.
(Pdb) s
--Call--
> /Users/taewoo/test.py(1)test_sum()
-> def test_sum(a,b):
(Pdb) r
--Return--
> /Users/taewoo/test.py(5)test_sum()->40
-> return a+b
  • w : Show current call stack.
(Pdb) w
  /Users/taewoo/.pyenv/versions/3.6.2/lib/python3.6/bdb.py(431)run()
-> exec(cmd, globals, locals)
  <string>(1)<module>()
  /Users/taewoo/test.py(9)<module>()
-> c=test_sum(a,b)
> /Users/taewoo/test.py(5)test_sum()->40
-> return a+b
  • cl : Clear all break points.
(Pdb) cl
Clear all breaks? y
  • b : Make break point to file’s or package’s specific function or line.
(Pdb) b 8
Breakpoint 1 at /Users/taewoo/test.py:8
(Pdb) b test_sum
Breakpoint 2 at /Users/taewoo/test.py:1
# Stop at line number 8
(Pdb) c
> /Users/taewoo/test.py(8)<module>()
-> b=30
# Stop at function
(Pdb) c
> /Users/taewoo/test.py(2)test_sum()
-> tmp=1
(Pdb) b
Num Type         Disp Enb   Where
1   breakpoint   keep yes   at /Users/taewoo/test.py:8
	breakpoint already hit 2 times
2   breakpoint   keep yes   at /Users/taewoo/test.py:1
	breakpoint already hit 1 time
  • a : Print function’s all arguments.
(Pdb)  s
--Call--
> /Users/taewoo/test.py(1)test_sum()
-> def test_sum(a,b):
(Pdb) a
a = 10
b = 30

Others

  • We can check value of variable using print function or just type it to pdb.
(Pdb) c
> /Users/taewoo/test.py(2)test_sum()
-> tmp=1
(Pdb) n
> /Users/taewoo/test.py(3)test_sum()
-> tmp=2
(Pdb) tmp
1
(Pdb) print(tmp)
1
(Pdb) type(data)
<class 'dict'>
(Pdb) data
{'data': [{'type': 'articles', 'id': '1', 'attributes': {'title': 'JSON API paints my bikeshed!', 'body': 'The shortest article. Ever.', 'created': '2015-05-22T14:56:29.000Z', 'updated': '2015-05-22T14:56:28.000Z'}, 'relationships': {'author': {'data': {'id': '42', 'type': 'people'}}}}], 'included': [{'type': 'people', 'id': '42', 'attributes': {'name': 'John', 'age': 80, 'gender': 'male'}}]}
  • Add break point in code.
  • Pdb will be stopped on import pdb; pdb.set_trace()
def test_sum(a,b):
    tmp=1
    tmp=2
    tmp=3
    return a+b

a=10
b=30
c=test_sum(a,b)

for i in range(1,10):
    a = a + i

import requests
import pdb; pdb.set_trace()
url = 'https://gist.githubusercontent.com/TWpower/771f9dfc8d9e1ddc0ecbdaea5b2e379e/raw/2c7785b4835138255bdadb71bd83702e53ac2677/test-example.json'

data = requests.get(url).json()
$ python -m pdb test.py
> /Users/taewoo/test.py(1)<module>()
-> def test_sum(a,b):
(Pdb) c
> /Users/taewoo/test.py(16)<module>()
-> url = 'https://gist.githubusercontent.com/TWpower/771f9dfc8d9e1ddc0ecbdaea5b2e379e/raw/2c7785b4835138255bdadb71bd83702e53ac2677/test-example.json'
(Pdb)


Reference

stderr를 /dev/null과 리다이렉트(Redirect)를 이용해 터미널 프롬프트 화면에 출력되지 않도록 해보자.


환경

  • Linux 기반 시스템
  • Bash shell(/bin/bash)
  • 리다이렉트(Redirect)


용어 정리

/dev/null이란?

  • /dev/null : NULL 장치라 불리는 부분으로 여기에 쓰여진 모든 값들을 버리지만 OS에는 작업에 성공했다고 보고하는 파일이다.
  • stderr/dev/null에 쓰면 표준 오류를 화면에서 안 볼 수 있다.

리다이렉트(Redirect)란?

  • Redirect('>'): 프로그램의 결과 혹은 출력(output)을 파일이나 다른 스트림으로 전달하거나 남길 때 사용하는 명령어다.
  • 참고 링크 : Redirect와 Pipe의 차이


사용 예제

find 명령어에서 stderr 무시하기

  • 기존에 출력되는 stderrPermission denied라고 나온다.
$ find / | grep neutron
find: ‘/run/docker’: Permission denied
find: ‘/run/containerd’: Permission denied
find: ‘/run/lxcfs’: Permission denied
find: ‘/run/sudo’: Permission denied
find: ‘/run/log/journal/50739525d1fb4eac9e863478fb990fed’: Permission denied
find: ‘/run/lvm’: Permission denied
  • /dev/nullstderr를 리다이렉트하니 Permission denied가 나오지 않는다.
  • 2stderr를 의미합니다.
find / 2> /dev/null | grep neutron
/home/twpower/test/neutron_patched
/home/twpower/test/neutron_patched/LICENSE
/home/twpower/test/neutron_patched/.gitignore
/home/twpower/test/neutron_patched/bin
...


참고자료

Redirect stderr to /dev/null so that ignore prints of standard errors in terminal prompt.


Environment and Prerequisite

  • Linux base system
  • Bash shell(/bin/bash)
  • Redirect


Terms

What is /dev/null?

  • /dev/null : Device file that discards all data written to it but reports that the write operation succeeded.
  • You can ignore standard error on screen when you write stderr to /dev/null.

What is redirect?

  • Redirect('>'): Redirect standard streams to user-specified locations like file or other stream.
  • Reference : Redirection (computing)


Usage example

Ignore stderr in find command

  • It prints Permission denied as stderr
$ find / | grep neutron
find: ‘/run/docker’: Permission denied
find: ‘/run/containerd’: Permission denied
find: ‘/run/lxcfs’: Permission denied
find: ‘/run/sudo’: Permission denied
find: ‘/run/log/journal/50739525d1fb4eac9e863478fb990fed’: Permission denied
find: ‘/run/lvm’: Permission denied
  • After redirect stderr to /dev/null, there is no Permission denied
  • 2 represents stderr
find / 2> /dev/null | grep neutron
/home/twpower/test/neutron_patched
/home/twpower/test/neutron_patched/LICENSE
/home/twpower/test/neutron_patched/.gitignore
/home/twpower/test/neutron_patched/bin
...


Reference

iperf3를 이용해 두 컴퓨터간 네트워크 성능을 측정해보자.


환경

  • Linux 기반 시스템
  • Bash shell(/bin/bash)
  • NIC 장치와 스위치 그리고 서브넷의 개념
  • ip 명령어에 대한 기본 사용법


iperf3 명령어

iperf3 명령어란?

iperf3 -s [ options ]
iperf3 -c server [ options ]
  • iperf3 : 두 컴퓨터간 네트워크 성능을 측정해주는 도구입니다.
  • iperf2 그리고 iperf도 있습니다.


설치법

  • CentOS
sudo yum install iperf3 -y
  • Ubuntu
sudo apt-get install iperf3 -y


사용법

  • 두개의 서버중에 하나를 서버 다른 하나를 클라이언트로 정하고 각각 아래 명령어를 사용해주시면 됩니다.
  • iperf3이 사용하는 port는 두 컴퓨터 다 열려있어야 합니다.
  • port는 5201번 포트를 사용합니다.

서버 컴퓨터

  • 다음 명령어 실행
iperf3 -s

클라이언트 컴퓨터

  • 다음 명령어 실행
  • IP ADDRESS에는 성능을 측정하고 싶은 다른 컴퓨터의 IP주소를 넣어주며 위에서 실행한 서버의 IP를 넣어주시면 됩니다.
iperf3 -c [IP ADDRESS]


예제

사용할 컴퓨터 정보

  • Server
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:3e:6c:4f:da:2b brd ff:ff:ff:ff:ff:ff
    inet 10.136.105.252/16 brd 10.136.255.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::503e:6cff:fe4f:da2b/64 scope link
       valid_lft forever preferred_lft forever
  • Client
$ ip addr show eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 9e:79:07:2a:26:e3 brd ff:ff:ff:ff:ff:ff
    inet 10.136.107.214/16 brd 10.136.255.255 scope global eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::9c79:7ff:fe2a:26e3/64 scope link
       valid_lft forever preferred_lft forever

서버에서 실행

# Update package list
$ sudo apt-get update -y

# Install package
$ sudo apt-get install iperf3 -y

# Run iperf3 server
$ iperf3 -s

클라이언트에서 실행

# Update package list
$ sudo apt-get update -y

# Install package
$ sudo apt-get install iperf3 -y

# Run iperf3 server
$ iperf3 -c 10.136.105.252

결과

  • Server
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 10.136.107.214, port 36216
[  5] local 10.136.105.252 port 5201 connected to 10.136.107.214 port 36218
[ ID] Interval           Transfer     Bandwidth
[  5]   0.00-1.00   sec   251 MBytes  2.11 Gbits/sec
[  5]   1.00-2.00   sec   238 MBytes  1.99 Gbits/sec
[  5]   2.00-3.00   sec   236 MBytes  1.98 Gbits/sec
[  5]   3.00-4.00   sec   236 MBytes  1.98 Gbits/sec
[  5]   4.00-5.00   sec   241 MBytes  2.02 Gbits/sec
[  5]   5.00-6.00   sec   237 MBytes  1.99 Gbits/sec
[  5]   6.00-7.00   sec   236 MBytes  1.98 Gbits/sec
[  5]   7.00-8.00   sec   242 MBytes  2.03 Gbits/sec
[  5]   8.00-9.00   sec   238 MBytes  2.00 Gbits/sec
[  5]   9.00-10.00  sec   237 MBytes  1.99 Gbits/sec
[  5]  10.00-10.04  sec  10.2 MBytes  2.07 Gbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth
[  5]   0.00-10.04  sec  0.00 Bytes  0.00 bits/sec                  sender
[  5]   0.00-10.04  sec  2.35 GBytes  2.01 Gbits/sec                  receiver
  • Client
Connecting to host 10.136.105.252, port 5201
[  4] local 10.136.107.214 port 36218 connected to 10.136.105.252 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec   262 MBytes  2.20 Gbits/sec  16168   97.6 KBytes
[  4]   1.00-2.00   sec   239 MBytes  2.00 Gbits/sec  16140    451 KBytes
[  4]   2.00-3.00   sec   240 MBytes  2.01 Gbits/sec  13883    136 KBytes
[  4]   3.00-4.00   sec   238 MBytes  2.00 Gbits/sec  11752    365 KBytes
[  4]   4.00-5.00   sec   238 MBytes  2.00 Gbits/sec  18333    297 KBytes
[  4]   5.00-6.00   sec   238 MBytes  1.99 Gbits/sec  19573    122 KBytes
[  4]   6.00-7.00   sec   238 MBytes  1.99 Gbits/sec  18483    115 KBytes
[  4]   7.00-8.00   sec   234 MBytes  1.96 Gbits/sec  17792    229 KBytes
[  4]   8.00-9.00   sec   241 MBytes  2.02 Gbits/sec  15119   1.20 MBytes
[  4]   9.00-10.00  sec   239 MBytes  2.00 Gbits/sec  23006   93.3 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  2.35 GBytes  2.02 Gbits/sec  170249             sender
[  4]   0.00-10.00  sec  2.35 GBytes  2.01 Gbits/sec                  receiver

iperf Done.


참고자료