• Pythonic: 파이썬 커스텀 컨테이너 생성하기


    * 커스텀 컨테이너의 바람직한 생성법

    컨테이너란?

    파이썬 클래스는 일종의 컨테이너로, 속성과 기능을 함께 캡슐화함으로써 데이터를 담고 있는 객체를 뜻한다. 파이썬 내장 컨테이너 타입으로는 리스트, 튜플, 세트 딕셔너리 등이 있다.

    예시1. 컨테이너 상속 - 리스트

    list의 표준기능을 전부 구현하면서, 중첩되는 아이템의 갯수를 카운팅하는 커스텀 기능을 가진 커스텀 컨테이너 예시이다.

    class CustomList(list):
        def __init__(self, initialize):
            super().__init__(initialize)
        
        def summary(self):
            rtn = {}
            for item in self:
                rtn.setdefault(item, 0)
                rtn[item] += 1
            return rtn
    
    clist = CustomList(['a', 'b', 'c', 'd', 'a', 'b'])
    summary = clist.summary()
    
    #  --- list 표준기능 --- 
    print(len(clist))
    clist.pop() 
    print(repr(clist))
    clist.append('d')
    print(repr(clist))
    
    # --- list 커스텀 기능 ---
    print(clist.summary())
    
    >>>
    6
    ['a', 'b', 'c', 'd', 'a']
    ['a', 'b', 'c', 'd', 'a', 'd']
    {'a': 2, 'b': 2, 'c': 1, 'd': 1} # <-- 커스텀 기능
    


  • Python: asynchronous cURL requests: AsyncURL


    비동기 cURL 리퀘스트 라이브러리 asyncurl

    최근 파이썬에 유명한 비동기 프레임워크 sanic을 살펴보다가, 내부 이벤트 루프를 uvloop로 대체하여 비동기통신을 빠르게 했다는 벤치마킹 결과를 감명깊게 읽었다. 결과적으로 asyncio의 퍼포먼스를 2배 이상 상승시킨 결과를 보고, 몇년 전 프로젝트에서 만들었었던 웹 크롤러를 떠올렸다.

    파이썬의 GIL이라는 녀석 때문에 당시에는 멀티프로세싱을 이용하여 병렬처리를 구현했었는데, 이번에는 하나의 스레드로 병렬처리를 구현하는 비동기 라이브러리를 구현하기로 마음 먹었다.

    의존성

    파이썬 3.6 이상부터 지원하며, 작성일 기준 상세 라이브러리 의존성은 다음과 같다.

    Package Version Description
    asyncio >=3.4.3 Asynchronous
    requests >=2.22.0 pycurl substitutes
    uvloop >=0.12.2 for event loop policy

    이벤트루프 대체제인 uvloop, 비동기 라이브러리 asyncio, 마지막으로는 통신을 위한 requests 이상 3가지이다. 개인적으로 pycurl은 설치 의존성도 까다롭고, 사용과 설치에 귀찮았던 기억들이 있어서 사용성 면에서 갑인 requests를 택하였다.



  • Pythonic: 파이썬의 비공개 필드


    * 파이썬 비공개 필드

    이름에서 예상할 수 있듯이, 정의 된 클래스내에서만 접근이 가능한 속성이다. 서브클래스에서도 부모클래스의 비공개 필드에 접근하지 못한다.

    컴파일러의 비공개 속성 컨트롤

    파이썬 컴파일러가 비공개 속성을 정의하는 방법은 비교적 간단하다.

    class MyTestObject(object):
        def __init__(self):
            self.public_value = 10
            self.__private_value = 1
    
    test = MyTestObject()
    print(test.__dict__)
    
    >>>
    {'public_value': 10, '_MyTestObject.__private_value': 1}
    

    상기 코드와 같이, __private_value에 접근하는 코드를 발견하면 _{class_name}__{private_field}로 변환한다.

    따라서 우리가 비공개 속성에 직접 접근할 때 보는 에러는 단순히 컴파일러가 변경한 속성의 이름을 찾지 못해 발생한다. 이 규칙을 이해하면 사실 우리는 마음만 먹으면 언제든지 객체내부를 조작하고, 비공개 속성에 접근할 수 있다.



  • Pythonic: 상태보존 클로저


    * 상태보존 클로저

    예시 1. 함수형태

    딕셔너리 타입의 before에 튜플로 구성 된 loop데이터를 순회하면서, 해당 value를 합산하고 새로운 값이 추가 될때마다 print를 찍는 함수이다. 클로저가 읽어지는 순서에 대해 잘 모른다면, 해당 문서를 참고할 것.

    defaultdict
    해당 자료구조는 찾을 수 없는 키에 접근할 때마다 호출될 함수를 후크(hook)으로 받는다.



  • Docker: 도커파일 제작 시, 기본 팁


    * 멀티플 도커 파일

    도커 오버라이드 (Default)

    도커 컴포즈가 컴포즈 파일을 따로 제시하지 않는 이상, docker-compose.yml을 읽는다는 것은 모두다 아는 사실이다. 하지만 실제로 도커 컴포즈는 기본적으로 다음과 같은 순서로 2개의 파일을 읽는다.

    1. docker-compose.yml
    2. docker-compose.override.yml (optional)

    docker-compose.override.yml은 옵셔널이며, 기본적으로는 docker-compose.yml에 베이스 설정을 하고, 오버라이드 파일통해서 해당 설정을 덮어쓰거나 생성한다. 주로 개발환경과 디플로이 환경을 구분하기 위해서 사용한다.