python을 처음 공부한 이래, 가상환경을 세팅하는 방법으로 conda밖에 없는 줄 알았다.

하지만 그동안 conda로 가상환경을 세팅하면서 자잘한 버그들로 불편했는데 (특히 MacOS M1과의 호환성이 정말 별로였다.)

다음 두 가지 큰 이유로 이번 기회에 다른 방식으로 넘어가게 되었다.

1. langchain 관련 dependency 문제:

- 우선 conda에 langchain 생태계가 없어서 pip로 일일히 다운받아야 했는데, dependency를 챙기는게 꽤나 번거로웠다.

- conda로 가상환경을 세팅하는 장점을 전혀 누릴 수가 없었다.

 

2. poetry를 통한 개발환경 세팅시 원인 모를 에러 거듭 발생

- 이번에 data platform팀 환경 위에 python 개발할 일이 있었는데, 로컬에서 pyspark을 실행하기 위한 가이드대로 해도 계속 에러가 났다.

- python version과 whl 파일 간의 충돌이 계속 발생했는데 아무리 구글링해도 해결되지 않았다.

- 찾아보니 conda 자체가 data science 분야에만 특화되어있기도 하고, 개발 환경에는 적합하지 않은 것 같아 로컬에 설치된 conda를 전부 제거하고 pyenv로 갈아타게되었다.

- conda를 쓰면 안되는 이유가 설명된 블로그: https://devbull.xyz/python-create-environment/ 

 

넘어가면서 거의 몇 시간을 삽질했기 때문에, 까먹지 않고자 남겨두고자 한다.

 

결론

- brew -> pyenv -> pipx -> poetry 순서로 삭제했다 재설치

- conda는 아예 삭제

 

1. python 가상환경은 왜 필요한가?

- python도 일종의 실행가능한 프로그램이다.

- 여러 library들이 이 프로그램에서 사용될 수 있도록 개발되는데, library들끼리 서로 가져다쓰기 때문에 dependency라는게 생긴다.

- 예를 들어 library B가 python 3.8에서 사용할 수 있도록 개발되고 library A의 ver 1을 사용한다고 하자.

- 만약 library A의 ver 2가 배포됐을 때, 사용자는 무턱되고 A, B의 최신 버전을 사용할 수가 없다.

- 아직 B는 A의 ver 1을 사용하고 있기 때문에 B를 설치하면서 A의 ver 1을 함께 설치해줘야 한다.

- 만약 다른 python 프로젝트에서 library C를 사용하고 이 C는 library A의 ver 2를 사용한다면?

- 이런 골치아픈 dependency 문제를 해결하기 위해 각각의 프로젝트마다 가상환경을 세팅한다.

- 그리고 이 가상환경마다 dependency 충돌이 안 일어나도록 일정의 config를 설정해둔다. 

    - poetry가 이런 솔루션 중 하나인데, 복잡한 사용법을 익혀야 한다.

    - 단순하게는 requirements.txt 파일을 만들어서 해당 프로젝트에 필요한 library들과 version을 관리한다.

 

2. pyenv

- 가상환경을 세팅하는 여러 툴이 있다.

- venv, virtualenv, pyenv, conda

- 각 장단점은 검색하거나 ChatGPT에 물어보면 잘 알 수 있으니 생략하고,

- 결론적으로 pyenv로 가상환경을 세팅하기로 했다.

- pyenv는 여러 명령어를 제공한다. (참고: https://shawn-dev.oopy.io/fe911cba-0b25-474c-9c3c-d18fd945c8b0)

- 가장 편하게 느껴진 점은 이것

    - python을 여러 버전으로 설치할 수 있다. (3.9, 3.10, 3.11)

    - 가상환경을 만들 때 설치한 python으로 세팅할 수 있고, 가상환경을 활성화 하는 것도 쉽다 (pyenv activate {가상환경 이름})

    - (핵심) python이 설치된 경로를 복잡하게 챙길 필요가 없다.

 

3. 원인 모를 문제들

- .whl 파일이 os가 지원하는 것과 다른 library가 요구하는 게 다르다는 에러가 거듭 났었다.

- 결국 해결 못해서 brew를 아예 삭제하고 다시 설치하니 해결되었다.

- 이 과정에서 conda로 설치한 python 경로와 pyenv로 설치한 python 경로가 매우 복잡하게 되어있는 것을 보고 한쪽으로 정리해야겠다고 결심했다.

- conda는 아예 삭제해버리고, pyenv도 삭제했다가 다시 설치했다.

배경

회사에서 새로운 Airflow Operator를 제작할 필요가 생겼다. 기존에 있는 Operator (Parent Operator)와 거의 유사한 동작을 하기 때문에, 상속을 통해 새로운 Operator(Child Operator)를 만들기로 결정했다. 새로 Child Operator는 다음 두 가지가 Parent Operator와 다르다.

  1. Parent Operator의 Instance 생성시 반드시 필요한 Parameter 중 일부가 Child Operator에서는 필요 없다.
  2. 가장 바깥에서 호출되는 execute Method는 Child Operator에서 동일하지만, execute 내부에서 사용하는 internal Method는 Parent와 다르다.

2가지 사항을 어떻게 Child Operator에 구현할 수 있는지 확인하자.

 

실험

코드

class Parent():
    def __init__(self, name: str, age: int, for_what: str) -> None:
        self.name = name
        self.age = age
        self.for_what = for_what
    
    def execute(self) -> None:
        message = self._internal_method()
        print(f"My name is {self.name}")
        print(message)
    
    def _internal_method(self) -> str:
        return "PARENT IS SUPER!"


class Child(Parent):
    def __init__(self, parent_name: str, **kwargs):
        super().__init__(for_what="", **kwargs)
        self.parent_name = parent_name
    
    def _internal_method(self) -> str:
        return "CHILD IS OVERRIDER!"


if __name__ == "__main__":
    c = Child(name = "HB", parent_name="Lee", age=27)
    c.execute()

 

실행 결과

$ python class-inheritance/override_practice.py
>> My name is HB
>> CHILD IS OVERRIDER!

 

결론

  1. super().__init__()에서 기존 Parent를 선언하는데 반드시 필요했던 parameter for_what에 ""를 집어넣었다.
    • 이게 효과적인 방법일지는 의문 - Python 자체에 class 상속후, 필수 parameter를 변경하는 방법은 없는 듯 하다
  2. "CHILD IS OVERRIDER!"가 출력됐다는 뜻은, execute에서 사용하는 _internal_method()가 override된 Child의 Method를 사용했다는 뜻이다.

 

Reference

 

How to choose an AWS profile when using boto3 to connect to CloudFront

I am using the Boto 3 python library, and want to connect to AWS CloudFront. I need to specify the correct AWS Profile (AWS Credentials), but looking at the official documentation, I see no way to

stackoverflow.com

 

2 - Sessions — AWS Data Wrangler 2.15.1 documentation

How Wrangler handle Sessions and AWS credentials? After version 1.0.0 Wrangler absolutely relies on Boto3.Session() to manage AWS credentials and configurations. Wrangler will not store any kind of state internally. Users are in charge of managing Sessions

aws-data-wrangler.readthedocs.io

 

dev = boto3.session.Session(profile_name='dev')

df = wr.athena.read_sql_query(
	boto3_session=dev,
	sql='''
    	select *
        from schema.table
    '''
)

+ Recent posts