본문 바로가기

파이썬 코딩의 기술

(22)
파이썬코딩의기술 - BW88 : 순환 의존성을 깨는 방법을 알아두라 (문제제기) 다른 사람들과 협업하다보면 불가피하게 모듈들이 상호 의존하는 경우가 생깁니다. 심지어 혼자 한 프로그램의 여러 부분을 홀로 작업할 때도 발생할 수 있습니다. - 다음 코드는 전역 선호도 설정에서 디폴트 문서 저장위치를 가져오는 대화창을 정의함 # dialog.py import app class Dialog: def __init__(self, save_dir): self.save_dir = save_dir ... save_dialog = Dialog(app.prefs.get('save_dir')) def show(): ... 문제는 prefs 객체가 들어있는 app 모듈이 프로그램 시작 시 대화창을 표시하고자 앞에서 정의한 dialog 클래스를 임포트한다는 점 입니다. # app.py impo..
파이썬코딩의기술 - BW87 : 호출자를 API로부터 보호하기 위해 최상위 Exception을 정의하라 모듈 API에서는 모듈 내에 정의한 함수 또는 클래스만큼이나 발생할 예외도 API 일부분으로서 중요합니다. 파이썬언어와 표준 라이브러리에는 이미 예외 계층 구조가 내장돼 있습니다. - (예) 직접 만든 모듈의 함수에 잘못된 파라미터가 전달되면 ValueError 예외를 던질 수도 있습니다. # my_module.py def determine_weight(volume, density): if density >> ERROR:root:예상치 못한 오류 Traceback (most recent call last): ... - (이점) logging.exception 함수가 잡아낸 스택 트레이스를 출력하기 떄문에 더 쉽게 이 상황을 디버깅할 수 있습니다. - (이점) 최상위 예외가 있으면 제공하는 API로부터 호..
파이썬코딩의기술 - BW 86 : 배포 환경을 설정하기 위해 모듈 영역의 코드를 사용하라 프로그램을 작성하는 궁극적인 목표는 프로덕션 환경에서 프로그램을 실행해 원하는 결과를 얻어내는 것 입니다. - venv를 쓰면 모든 환경에서 똑같은 파이썬 패키지가 설치되기 할 수 있음 (문제제기) 문제는 프로덕션 환경의 경우 개발 환경에서 재현하기 힘든 외부 가정이 많을 수 있다는 점 입니다. - (예) 웹 서버 컨테이너 안에서 프로그램을 실행시키되 프로그램이 데이터베이스에 접근할 수 있도록 허용하고 싶다고 하자. - 이때, 프로그램에서 한 줄만 변경한 뒤 제대로 동작하는지 검증하고 싶을 뿐인데 이 모든 작업을 다시해야 한다면 비용이 너무 비싸다. 이러한 문제를 우회하는 가장 좋은 방법은 프로그램을 시작할 때 프로그램 일부를 오버라이드해서 배포되는 환경에 따라 다른 기능을 제공하도록 만드는 것입니다. ..
파이썬코딩의기술 - BW78 : 목을 사용해 의존 관계가 복잡한 코드를 테스트 하라 테스트를 작성할 때 필요한 공통 기능으로 사용하기에 너무 느리거나 어려울 함수와 클래스의 목을 만들어 사용하는 기능이 있습니다. - (예) 동물원에서 먹이 주는 시간을 관리하는 프로그램이 필요함 - (예) 다음 코드는 특정 종에 속하는 모든 동물과 그 동물들에게 가장 최근에 먹이를 준 시간을 데이터베이스에 질의해서 반환하는 함수다. class DatabaseConnection: ... def get_animals(database, species): # 데이터베이스에 질의한다 ... # (이름, 급양 시간) 튜플 리스트를 반환한다 >>> Traceback (most recent call last): File "Betterway78.py", line 9, in database = DatabaseConnect..
파이썬코딩의기술 - BW77 : setUp, tearDown, setUpModule, tearDownModule을 사용해 각각의 테스트를 격리하라 TestCase 클래스에서는 테스트 메서드를 실행하기 전에 테스트 환경을 구축해야 하는 경우가 자주 있습니다. - 이런 테스트 과정을 테스트 하네스(test harness)라고 부르기도 합니다. setUp, tearDown 두 메서드를 활용하면 각 테스트를 서로 격리된 상태에서 실행할 수 있습니다. - 테스트 간의 격리는 테스트를 제대로 진행하기 위해 가장 중요한 실무 지침 입니다 - setUp은 테스트 메서드를 실행하기 전에 호출됨 - tearDown 메서드는 테스트 메서드를 실행한 다음에 호출됨 - (예) 테스트를 진행하기 전에 임시 디렉터리를 만들고 테스트가 끝난 후 디렉터리 내용을 지우는 TestCase 클래스를 정의한 코드다. # environment_test.py from pathlib imp..
파이썬코딩의기술 - BW55 : Queue를 사용해 스레드 사이의 작업을 조율하라 파이썬 프로그램이 동시에 여러 일을 수행한다면, 각 작업을 잘 조율해야 합니다. - 동시성 작업을 처리할 때 가장 유용한 방식은 함수 파이프라인 입니다. - 파이프라인은 공장 조립 라인처럼 작동함 - 파이프라인에는 순차적으로 실행해야 하는 여러 단계가 있고, 각 단계마다 실행할 구체적인 함수가 정해짐 - 파이프라인의 한쪽 끝에는 새로운 작업이 계속 추가됨 - 각 함수는 동시에 실행될 수 있고 각 단계에서 처리해야 하는 일을 담당함 작업은 매 단계 함수가 완료될 때마다 다음 단계롤 전달되며, 더 이상 실행할 단계가 없을 때 끝납니다. - 이런 접근 방법은 작업 처리에 블로킹 I/O나 하위 프로세스가 포함되는 경우에 특히 좋음 - 파이썬에서는 블로킹 I/O나 하위 프로세스를 더 쉽게 병렬화할 수 있기 때문 ..
파이썬코딩의기술 - BW54 : 스레드에서 데이터 경합을 피하기 위해 Lock을 사용하라 초보 파이썬 프로그래머는 전역 인터프리터 락(GIL)을 배운뒤, 코드에서 더이상 상호 배제 락(뮤텍스)을 사용하지 않아도 되는 것으로 생각하곤 합니다. GIL이 다중 CPU에서 파이썬 스레드들이 병렬적으로 실행될 수 없게 막는다면, 파이썬 스레드들이 프로그램의 데이터 구조에 동시에 접근할 수 없게 맞는 락 역할도 해줘야 하지 않을까 ?? 하지만 GIL이 동시 접근을 보장해주는 락 역할을 하는 것 처럼 보여도 실제로는 전혀 그렇지 않습니다. - 파이썬 스레드는 한 번에 단 하난만 실행될 수 있음 - 파이썬 인터프리터에서 어떤 스레드가 데이터 구조에 대해 수행하는 연산은 연속된 두 바이트코드 사이에서 언제든 인터럽트 될 수 있음 ( 여러 스레드가 같은 데이터 구조에 동시에 접근하면 위험!! ) - (예) 병..
파이썬코딩의기술 - Betterway 48 : __init_subclass__를 사용해 하위 클래스를 검증하라 메타클래스의 가장 간단한 활용법 중 하나는 어떤 클래스가 제대로 구현됐는지 검증하는 것 입니다. - (예) 메서드를 오버라이드 하도록 요청 / 클래스 애트리뷰트 사이에 엄격한 관계를 가지도록 요구/ 복잡한 클래스 계층을 설계할 때 어떤 스타일 강제로 지키도록 만듬 - 메타클래스는 이런 목적을 달성할 수 있음 - 새로운 하위 클래스가 정의될 때마다 이런 검증 코드를 수행하는 신뢰성 있는 방법을 제공하기 때문. 어떤 클래스 타입의 객체가 실행 시점에 생성될 때 클래스 검증 코드를 __init__ 메서드 안에서 실행하는 경우도 종종 있습니다. 하위 클래스를 검증하는 메타클래스를 정의하는 방법을 살펴보기 전에, 일반적인 객체에 대해 메타클래스가 어떻게 작동하는지 이해하는 것이 중요합니다. - 메타클래스는 typ..
파이썬코딩의기술 : Betterway 47 - 지연 계산 애트리뷰트가 필요하면 __getattr__, __getattribute__, __setattr__을 사용하라 스키마를 표현하는 클래스를 더 일반화하는 방법 파이썬에서는 __getattr__이라는 특별 메서드를 사용해 이런 동적 기능을 활용할 수 있다. - 어떤 클래스 안에 __getattr__ 메서드 정의가 있으면, 이 객체의 인스턴스 딕셔너리에서 찾을 수 없는 애트리뷰트에 접근할 때만다 __getattr__이 호출됩니다. class LazyRecord: def __init__(self): self.exists = 5 def __getattr__(self, name): value = f'{name}를 위한 값' setattr(self, name, value) return value >>> 이전: {'exists': 5} foo: foo를 위한 값 이후: {'exists': 5, 'foo': 'foo를 위한 값'..
파이썬코딩의기술 : Betterway 46 - 재사용 가능한 @property 메서드를 만들려면 디스크립터를 사용하라 @property 내장 기능의 가장 큰 문제점은 재사용성이다. @property가 데코레이션하는 메서드를 같은 클래스에 속하는 여러 애트리뷰트로 사용할 수는 없다. 그리고, 서로 무관한 클래스 사이에서 @property 데코레이터를 적용한 머세드를 재사용할 수도 없다. 예를 들어, 학생의 숙제 점수가 백분율 값인지 검증하고 싶다고 하자. class Homework: def __init__(self): self._grade = 0 @property def grade(self): return self._grade @grade.setter def grade(self, value): if not (0 >> 두 번째 쓰기 점수 75 맞음 첫 번째 쓰기 점수 82 틀림 문제는 writing_grade 클래스 애트리..