17 Nov 2017
|
Python
logging 모듈
Python에서는 로그 출력을 위한 logging 모듈을 제공합니다. 아주 간단히 사용할 수 있으며, print 함수 등을 통해 콘솔창에 지저분하게 출력하는 것보다 logging 모듈을 사용하는 것을 추천합니다.
로그 레벨
Python에서 로그 레벨은 다음과 같습니다. 안드로이드 등에서와 거의 동일합니다.
- DEBUG
- INFO
- WARNING
- ERROR
- CRITICAL
간단한 logging 모듈 사용 예제
import logging as log
log.basicConfig(filename='./log.txt', level=log.DEBUG)
if __name__ == '__main__':
log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')
출력 결과는 다음과 같습니다.
DEBUG:root:debug
INFO:root:info
WARNING:root:warning
ERROR:root:error
CRITICAL:root:critical
basicConfig 함수를 통해서 로그 파일의 이름을 지정할 수 있고, filemode 속성의 값을 a, w 등으로 지정할 수 있습니다. a의 경우 기존 파일에 이어서 기록(Append)하며, w의 경우 기존 파일 내용을 삭제하고 새로 작성합니다.
콘솔창과 파일에 동시에 로그 남기기
import logging
import logging.handlers
log = logging.getLogger('snowdeer_log')
log.setLevel(logging.DEBUG)
fileHandler = logging.FileHandler('./log.txt')
streamHandler = logging.StreamHandler()
log.addHandler(fileHandler)
log.addHandler(streamHandler)
if __name__ == '__main__':
log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')
import logging
import logging.handlers
log = logging.getLogger('snowdeer_log')
log.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(levelname)s] (%(filename)s:%(lineno)d) > %(message)s')
fileHandler = logging.FileHandler('./log.txt')
streamHandler = logging.StreamHandler()
fileHandler.setFormatter(formatter)
streamHandler.setFormatter(formatter)
log.addHandler(fileHandler)
log.addHandler(streamHandler)
if __name__ == '__main__':
log.debug('debug')
log.info('info')
log.warning('warning')
log.error('error')
log.critical('critical')
출력 결과는 다음과 같습니다.
[DEBUG] (log_test.py:19) > debug
[INFO] (log_test.py:20) > info
[WARNING] (log_test.py:21) > warning
[ERROR] (log_test.py:22) > error
[CRITICAL] (log_test.py:23) > critical
| 이름 |
포맷 |
설명 |
| asctime |
%(asctime)s |
날짜 시간, 밀리세컨드까지 출력. ex) 2017.11.17 12:31:45,342 |
| created |
%(created)f |
생성 시간 출력 |
| filename |
%(filename)s |
파일명 |
| funcnName |
%(funcName)s |
함수명 |
| levelname |
%(levelname)s |
로그 레벨(DEBUG, INFO, WARNING, ERROR, CRITICAL) |
| levelno |
%(levelno)s |
로그 레벨을 수치화해서 출력(10, 20, 30, …) |
| lineno |
%(lineno)d |
소스의 라인 넘버 |
| module |
%(module)s |
모듈 이름 |
| msecs |
%(msecs)d |
로그 생성 시간에서 밀리세컨드 시간 부분만 출력 |
| message |
%(message)s |
로그 메시지 |
| name |
%(name)s |
로그 이름 |
| pathname |
%(pathname)s |
소스 경로 |
| process |
%(process)d |
프로세스(Process) ID |
| processName |
%(processName)s |
프로세스 이름 |
| thread |
%(thread)d |
Thread ID |
| threadName |
%(threadName)s |
Thread Name |
파일의 최대 용량 및 새로운 파일 생성하는 방법
RotatingFileHandler 함수를 이용해서 파일의 최대 크기 및 새로운 파일을 생성할 때 최대 개수를 지정해줄 수 있습니다. 아래와 같은 코드를 이용해서 최대 10MB씩, 총 20개의 로그 파일을 만들어서 순환하도록 할 수 있습니다.
log_max_size = 10 * 1024 * 1024
log_file_count = 20
fileHandler = logging.handlers.RotatingFileHandler(filename='./log.txt', maxBytes=log_max_size,
backupCount=log_file_count)
logging.handlers
위에서는 FileHandler와 StreamingHandler 및 RotatingFileHandler 등을 사용했었는데 이외에도 다양한 핸들러들이 존재합니다.
| 핸들러 |
설명 |
| SocketHandler |
외부 로그 서버로 소켓을 통해 전송 |
| DatagramHandler |
UDP 통신을 통해 외부 서버로 전송 |
| SysLogHandler |
Unix 류의 syslog 데몬에게 로그 전송 |
| SMTPHandler |
메일로 로그 전송 |
| HTTPHandler |
HTTP를 통해 로그 전송 |
17 Nov 2017
|
용어
네트워크
일반적으로 사용하는 포트 번호 및 프로토콜
일반적으로 사용하는 포트 번호 및 프로토콜은 다음과 같습니다.
| 프로토콜 |
명령어 |
포트 번호 |
| Echo |
echo |
7 |
| Daytime |
daytime |
13 |
| File Transfer |
ftp |
21/20 |
| Secure Shell |
ssh |
22 |
| Telnet Terminal |
telnet |
23 |
| Simple Mail Transfer |
smtp |
25 |
| Domain Name Service |
domain |
53 |
| Trivial File Transfer |
tftp |
69 |
| Finger |
finger |
79 |
| HyperText transfer |
http |
80/84/8000 |
| NetNews |
nntp |
119 |
15 Nov 2017
|
Python
라즈베리파이
라즈베리파이에서 pyAudio 모듈 사용하기
라즈베리파이에서 pyAudio 모듈을 사용해서 오디오 녹음을 하고 재생하는 예제 코드입니다. 오디오 파일 녹음과 재생은 Streaming 형태로 이루어지며, 각각 wav 파일로 저장하고 재생합니다.
pyAudio 모듈 설치
먼저 터미널에서 다음 명령어를 입력해서 pyAudio를 설치합니다.
sudo apt install python3-pyaudio
pyaudio_recorder.py
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("Start to record the audio.")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("Recording is finished.")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
pyaudio_player.py
import pyaudio
import wave
import sys
CHUNK = 1024
if len(sys.argv) < 2:
print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
sys.exit(-1)
wf = wave.open(sys.argv[1], 'rb')
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
data = wf.readframes(CHUNK)
while data != '':
stream.write(data)
data = wf.readframes(CHUNK)
stream.stop_stream()
stream.close()
p.terminate()
14 Nov 2017
|
Python
라즈베리파이
라즈베리파이에서 오디오 파일로 녹음하기
pyalsaaudio 모듈 설치
라즈베리파이(Raspberry PI)에서 Python을 이용해서 오디오 녹음을 하는 예제입니다.
라즈베리파이도 기본적으로 Linux 기반이다보니 ‘ALSA’ 오디오 라이브러리를 사용합니다. Python에서도 마찬가지로 pyalsaaudio라는 모듈을 설치해야 오디오 장비에 접근할 수 있습니다.
터미널에서 다음 명령어로 pyalsaaudio 모듈을 설치합니다.
sudo pip3 install pyalsaaudio
만약 pyalsaaudio 설치 도중에
alsaaudio.c:28:28: fatal error: alsa/asoundlib.h: No such file or directory
#include <alsa/asoundlib.h>
^
compilation terminated.
error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1
위와 같은 오류 메세지가 발생했을 경우에는 다음 명령어를 이용해서 libasound2-dev를 먼저 설치해줘야 합니다.
sudo apt-get install libasound2-dev
오디오 녹음하는 Python 예제 코드
from __future__ import print_function
import sys
import time
import getopt
import alsaaudio
def usage():
print('usage: recordtest.py [-d <device>] <file>', file=sys.stderr)
sys.exit(2)
if __name__ == '__main__':
device = 'default'
opts, args = getopt.getopt(sys.argv[1:], 'd:')
for o, a in opts:
if o == '-d':
device = a
if not args:
usage()
f = open(args[0], 'wb')
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NONBLOCK, device=device)
inp.setchannels(1)
inp.setrate(44100)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(160)
loops = 1000000
while loops > 0:
loops -= 1
l, data = inp.read()
if l:
f.write(data)
time.sleep(.001)
aplay로 녹음된 파일 확인
aplay로 정상적으로 녹음이 되었는지 확인합니다.
aplay -t raw -c 1 -f S16_LE -r 44100 test.raw
13 Nov 2017
|
Python
Condition Variable
조건 변수(Condition Variable)는 내부에 Thread 대기 큐를 갖고 있습니다. wait() 메소드가 호출된 Thread는 이 대기 큐에 들어가게 되고 Sleep 상태가 되며, notify()나 notifyAll() 메소드에 의해 깨어나게 됩니다.
조건 변수를 활용한 생산자/소비자 패턴(Producer/Consumer Pattern) 예제는 다음과 같습니다.
Producer/Consumber 패턴 예제
Producer는 물건(item)을 생산하여 queue에 차곡차곡 쌓아가며, Consumer는 queue에 쌓여있는 물건을 하나씩 가져갑니다. 단, queue에 쌓인 물건이 하나도 없을 경우에는 대기(wait)를 합니다.
import threading
import time
CONSUMER_COUNT = 10
PRODUCER_COUNT = CONSUMER_COUNT // 2
queue = []
cv = threading.Condition()
item_id = 0
class Consumer(threading.Thread):
def __init__(self, id):
threading.Thread.__init__(self)
self.id = id
def run(self):
for i in range(5):
cv.acquire()
while len(queue) < 1:
print('consumer({}) waiting...'.format(self.id))
cv.wait()
print('consumer({}) -> item({})'.format(self.id, queue.pop(0)))
cv.release()
time.sleep(0.5)
class Producer(threading.Thread):
def run(self):
global item_id
for i in range(10):
cv.acquire()
item_id += 1
queue.append(item_id)
cv.notify()
cv.release()
time.sleep(0.7)
threads = []
for i in range(CONSUMER_COUNT):
threads.append(Consumer(i))
for i in range(PRODUCER_COUNT):
threads.append(Producer())
for th in threads:
th.start()
for th in threads:
th.join()
print('<End>')
실행 결과
consumer(0) waiting...
consumer(1) waiting...
consumer(2) waiting...
consumer(3) waiting...
consumer(4) waiting...
consumer(5) waiting...
consumer(6) waiting...
consumer(7) waiting...
consumer(8) waiting...
consumer(9) waiting...
consumer(0) -> item(1)
consumer(1) -> item(2)
consumer(2) -> item(3)
consumer(3) -> item(4)
consumer(4) -> item(5)
consumer(4) waiting...
consumer(2) waiting...
consumer(3) waiting...
consumer(0) waiting...
consumer(1) waiting...
consumer(6) -> item(6)
consumer(7) -> item(7)
consumer(8) -> item(8)
consumer(5) -> item(9)
consumer(9) -> item(10)
consumer(9) waiting...
consumer(8) waiting...
consumer(5) waiting...
consumer(6) waiting...
consumer(7) waiting...
consumer(4) -> item(11)
consumer(2) -> item(12)
consumer(0) -> item(13)
consumer(3) -> item(14)
consumer(1) -> item(15)
consumer(1) waiting...
consumer(4) waiting...
consumer(0) waiting...
consumer(2) waiting...
consumer(3) waiting...
consumer(9) -> item(16)
consumer(8) -> item(17)
consumer(5) -> item(18)
consumer(6) -> item(19)
consumer(7) -> item(20)
consumer(9) waiting...
consumer(6) waiting...
consumer(7) waiting...
consumer(8) waiting...
consumer(5) waiting...
consumer(1) -> item(21)
consumer(4) -> item(22)
consumer(0) -> item(23)
consumer(3) -> item(24)
consumer(2) -> item(25)
consumer(1) waiting...
consumer(2) waiting...
consumer(3) waiting...
consumer(0) waiting...
consumer(4) waiting...
consumer(9) -> item(26)
consumer(6) -> item(27)
consumer(7) -> item(28)
consumer(8) -> item(29)
consumer(5) -> item(30)
consumer(9) waiting...
consumer(5) waiting...
consumer(8) waiting...
consumer(6) waiting...
consumer(7) waiting...
consumer(1) -> item(31)
consumer(3) -> item(32)
consumer(0) -> item(33)
consumer(2) -> item(34)
consumer(4) -> item(35)
consumer(1) waiting...
consumer(2) waiting...
consumer(3) waiting...
consumer(4) waiting...
consumer(0) waiting...
consumer(9) -> item(36)
consumer(5) -> item(37)
consumer(8) -> item(38)
consumer(6) -> item(39)
consumer(7) -> item(40)
consumer(9) waiting...
consumer(6) waiting...
consumer(7) waiting...
consumer(8) waiting...
consumer(5) waiting...
consumer(1) -> item(41)
consumer(2) -> item(42)
consumer(3) -> item(43)
consumer(4) -> item(44)
consumer(0) -> item(45)
consumer(9) -> item(46)
consumer(7) -> item(47)
consumer(6) -> item(48)
consumer(8) -> item(49)
consumer(5) -> item(50)
<End>
실제 Queue를 활용한 Producer/Consumer 패턴 예제
위의 예제에서는 queue라는 이름을 가진 리스트를 사용해서 구현했지만, 파이썬에서는 Multi-Threading 환경에서 사용할 수 있는 queue 모듈을 제공하고 있습니다.
queue 모듈을 사용한 예제는 아래와 같습니다.
import threading
import time
from queue import Queue
CONSUMER_COUNT = 10
PRODUCER_COUNT = CONSUMER_COUNT // 2
que = Queue(100)
item_id = 0
class Consumer(threading.Thread):
def __init__(self, id):
threading.Thread.__init__(self)
self.id = id
def run(self):
for i in range(5):
print('consumer({}) -> item({})'.format(self.id, que.get()))
time.sleep(0)
class Producer(threading.Thread):
def run(self):
global item_id
for i in range(10):
item_id += 1
que.put(item_id)
time.sleep(0.7)
threads = []
for i in range(CONSUMER_COUNT):
threads.append(Consumer(i))
for i in range(PRODUCER_COUNT):
threads.append(Producer())
for th in threads:
th.start()
for th in threads:
th.join()
print('<<End>')