프로그래밍 언어/Python 13

memoryview 성능 테스트 ( feat.timeit, 버퍼프로토콜 )

timeit 라이브러리는 작은단위의 코드에 실행시간을 테스트할 수 있는 유용한 도구입니다. 이 도구를 사용하여 파이썬에서 제공해주는 단순한 바이트배열과 memoryview 라는 객체를 활용하였을 때 성능적으로 얼마나 큰 차이점이 발생하고 왜 이런 차이점이 발생하는지 알아보겠습니다 import os import timeit video_data = 100 * os.urandom(1024 * 1024) byte_offset = 1234 size = 20 * 1024 * 1024 def run_test(): chunk = video_data[byte_offset:byte_offset + size] result = timeit.timeit( stmt='run_test()', globals=globals(), nu..

asyncio를 활용해 간단하게 서버 구현한 코드 리뷰하기

asyncio로 서버를 구성하는 코드예제를 보고, 그냥 넘어가는 것보단 정리하면서 개념도 같이 정리해보면 좋을 것 같아서 코드리뷰 느낌으로 글을 작성해보았습니다! 전체코드를 보고 싶으신 분들은 아래 깃헙주소를 참고해주시면 좋을 것 같아요 https://github.com/bslatkin/effectivepython/blob/master/example_code/item_61.py#L278 또한 해당 코드에서의 목적은 클라이언트와 서버와의 숫자맞추기 게임로직을 구현한 것인데, 게임로직 함수 구현내용은 거의 생략을 했음을 참고해주시면서 보면 좋을 것 같습니다. 코드는 최대한 발생순서대로 정리하였습니다 async def main_async(): address = ('127.0.0.1', 4321) server ..

소켓코드를 보고 현상정리 ( feat. 버퍼 )

class EOFError(Exception): pass # 서버는 한번에 하나씩 처리, 클라이언트 세션상태 유지하는 클래스 class ConnectionBase: # 3 def __init__(self, connection): self.connection = connection self.file = connection.makefile('rb') def send(self, command): line = command + '\\n' data = line.encode() self.connection.send(data) def receive(self): line = self.file.readline() if not line: raise EOFError('Connection closed') return line..

with와 @contextlib.contextmanager

파이썬으로 작성된 소켓연결 코드를 보는 와중에 소켓연결할 때, with 접두사로 활용하는 모습들이 보였다. 혹은, @contextlib.contextmanager 라는 데코레이터를 붙힌 후, 해당 fn 를 with문으로 활용하는 문법들을 보면서, 대체 with를 왜 쓰는것이고, 무엇을 하는 역활인지 궁금했고 찾아보았다. with 문은 Python의 컨텍스트 관리 프로토콜을 사용하는 문법이며, 주로 리소스 관리에 사용되며, 이를 통해 파일, 네트워크 연결, 데이터베이스 연결 등의 리소스를 안전하게 사용하고 정리할 수 있다고 한다. with 문의 3단계로 걸쳐 실행된다 진입: with 블록에 진입할 때, 컨텍스트 관리자의 enter 메서드가 호출됩니다. 이 메서드는 필요한 리소스를 할당하거나 초기화할 수 있..

컨텍스트 스위칭으로부터의 예상치 못한 결과 ( feat.GIL )

파이썬에서 동시성,병렬성에 대한 학습을 하면서 이해했던 것들을 재검토하는 시간에 Thread 안에 subprocess를 만나면 블로킹을 하고 다음 Thread로 넘어가는지에 대한 궁금증이 생겼다 바로 코드로 확인해보았다 import threading import subprocess import time def run_command(): print("Starting command...") subprocess.run(["sleep", "5"]) # 5초 동안 sleep하는 외부 명령 print("Command finished.") def do_other_stuff(): for i in range(3): print("Doing other stuff...") time.sleep(1) run_command() d..

Thread와 Queue를 활용한 파이프라인 구현하기( feat. 콘웨이 생명게임 )

더보기 콘웨이의 생명 게임(Conway's Game of Life)은 1970년에 수학자 존 콘웨이(John Conway)에 의해 고안된 세포 자동자(cellular automaton)입니다. 이 게임은 "게임"이라는 이름을 가지고 있지만, 플레이어의 참여 없이 자동으로 진행되는 시뮬레이션입니다. 게임의 규칙은 다음과 같습니다: 생존: 어떤 세포에 인접한 8개의 세포 중 정확히 2개 또는 3개가 살아 있으면, 다음 세대에서 그 세포는 살아 있습니다. 사망: 어떤 세포에 인접한 8개의 세포 중 살아 있는 세포가 2개 미만이면, 그 세포는 고립되어 사망합니다. 또한, 살아 있는 세포가 3개 초과로 인접해 있으면, 그 세포는 과밀로 인해 사망합니다. 번식: 어떤 세포에 인접한 8개의 세포 중 정확히 3개가 살..

파이썬에서 외부 터미널 명령어 사용하기 ( subprocess )

파이썬에서 subprocess 를 활용해 자식 프로세스를 실행하면서, 자식 프로세스의 입출력 스트림을 관리 및 활용할 수 있습니다 import subprocess result = subprocess.run(['echo', 'Hello from subprocess!'], capture_output=True, text=True) print(result.stdout) # Hello from subprocess! 위 코드를 통해 subprocess에 터미널 명령을 넣어주면 아래와 같은 결과값을 얻을 수 있음을 확인할 수 있습니다. 만약 내가 터미널 명령을 통한 결과값을 이용해 파이프라인을 구축하고 싶다면 Popen 클래스를 활용해 유닉스 스타일의 파이프라인을 구축해볼 수 있을 것 같은데요. 여기서 유닉스 스타일..

GIL를 무조건 신뢰하면 안되는 이유( feat.스레드 감수성 )

나는 생각했다. 그러면 GIL 때문에 쓰레드 작업에서 락걸거나, 따로 통제할 필요가 없겠네. GIL 특성상 무조건 딱 하나의 스레드만 실행시켜주니깐! 하지만 이 말은 틀렸다. GIL는 동시접근을 보장해주는 락역활이라고 생각했지만 그렇지않다. 그 이유는 코드로 확인해보자. class Counter: def __init__(self): self.count = 0 def increment(self, offset): self.count += offset def worker(sensor_index, how_many, counter): BARRIER.wait() for _ in range(how_many): counter.increment(1) # Example 3 from threading import Barri..

두 코드의 차이점을 설명하시요( feat. Python,쓰레드, GIL, 병렬 I/O)

import select import socket def slow_systemcall(): select.select([socket.socket()], [], [], 0.1) start = time.time() for _ in range(5): slow_systemcall() end = time.time() delta = end - start print(f'Took {delta:.3f} seconds') # Took 0.526 seconds import select import socket def slow_systemcall(): select.select([socket.socket()], [], [], 0.1) start = time.time() threads = [] for _ in range(5): t..

클래스를 디버깅해보자(feat.메타클래스,클래스 데코레이터)

클래스를 디버깅 하기위해 구현하는 다양한 방법(함수 데코레이터, 메타클래스, 클래스 데코레이터)들을 사용해볼 수 있다. 해당 방법들을 사용하기 이전에 클래스를 디버깅하려면 어떻게 해야할까? 가장 쉬운 방법은 디버깅모드에 들어가서 break point를 찍는 방법이겠지만, 지금 구현하고 싶은 것은 해당 클래스들이 동작들 중에 생성되는 변수들을 print 찍는 것이 목표이다 클래스 내부에서 애트리뷰트를 변경하거나 받아갈 때 마다 디버깅할 수 있는 방법을 함수 데코레이터, 메타클래스를 활용하면서 점층적으로 리팩토링하면서 최종적으로는 클래스 데코레이터를 사용하여 리팩토링 하는 방법을 알아보자. from functools import wraps def trace_func(func): if hasattr(func,..