Logo

파이썬에서 환경 변수 다루기 (os.environ)

여러 환경에 파이썬 애플리케이션을 배포하려면 환경 변수라는 것을 이용해야하는데요. 이번 포스팅에서는 파이썬에서 환경 변수에 어떻게 접근하고 설정할 수 있는지에 대해서 알아보겠습니다.

환경 변수란?

먼저 환경 변수(environment variable)가 무엇인지 간단하게 짚고 넘어가면 좋을 것 같은데요. 환경 변수는 운영 체제(operating system) 수준에서 설정되는 변수로, 주로 애플레케이션 수준에서 설정하기가 불가능하거나 어려운 값들을 환경 변수로 관리하는 경우가 많죠.

환경 변수를 이용하면 애플리케이션 코드를 수정하지 않고도 개발, 테스트, 운영 등 배포 환경에 따라 설정값을 유연하게 변경할 수 있어서 이식성(portability)과 유지 보수성 측면에서 큰 이점이 있습니다.

대표적인 예로, 데이터베이스(DB) 설정을 들 수 있는데요. 운영 환경에서는 데이터 센터나 클라우드 인프라 상의 상용 DB를 사용하고, 개발 환경에서는 개발자의 PC 상에서 로컬 DB를 사용하는 경우에 환경 변수를 이용해서 각 환경 별로 데이터베이스 설정을 관리하는 경우가 많습니다.

뿐만 아니라, 데이터베이스의 비밀번호나 서드파티(3rd-party) 서비스의 API 키와 같이 민감한 인증 정보는 GitHub와 같은 코드 저장소(repository)에 올리면 상당히 위험할 수 있기 때문에 환경 변수로 저장해놓고 사용하는 것이 권장됩니다.

os 내장 모듈

파이썬에서는 기본적으로 내장되어 있는 os 모듈을 통해서 환경 변수가 관리되는데요. 우선 터미널을 열고 파이썬 인터프리터를 실행한 후, os 내장 모듈을 불러오는 것부터 시작해보겠습니다.

$ python
Python 3.11.2 (main, Apr  7 2023, 15:52:33) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os

os.environ 속성

운영 체제에 설정되어 있는 모든 환경 변수는 os 모듈의 environ이라는 속성을 통해서 접근이 가능합니다. 이 os.environ 속성은 마치 파이썬 내장 자료구조인 사전(dictionary)을 사용하듯이 사용할 수 있습니다.

예를 들어, HOME이라는 환경 변수에 저장되어 있는 값은 다음과 같이 읽어올 수 있습니다.

>>> os.environ['HOME']
'/Users/dale'

동일한 방식으로 SHELL이라는 환경 변수에 저장되어 있는 값도 읽어올 수 있겠죠?

>>> os.environ["SHELL"]
'/bin/zsh'

아직 설정해준 적이 없는 API_KEY라는 환경 변수에 저장된 값을 읽어오려고 하면 어떻게 될까요? 다음과 같이 KeyError가 발생하게 되는데요.

>>> os.environ['API_KEY']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen os>", line 679, in __getitem__
KeyError: 'API_KEY'

파이썬에서 일반적으로 사전에 존재하지 않는 키를 넘길 경우, KeyError가 발생하는 것과 같은 이치라고 보시면 될 것 같습니다.

따라서 애플리케이션 코드를 작성할 때는 환경 변수가 존재하지 않는 경우에 대한 적당한 예외 처리를 해줘야 하는데요. 어떤 환경 변수가 없을 때, 오류를 발생시키는 대신에 None을 반환받고 싶은 경우에는 사전과 동일하게 get() 메서드를 사용하면 됩니다.

>>> os.environ.get('API_KEY') is None
True

get() 메서드의 두 번째 인자로 기본값을 넘길 수도 있습니다. 꼭 설정해주지 않아도 되는 환경 변수에 유용하게 사용됩니다.

>>> os.environ.get('API_KEY', 'abc')
'abc'

os.getenv 함수

os 모듈의 getenv() 함수를 사용하면 좀 더 간결한 코드로 os.environ.get() 함수와 동일한 효과를 얻을 수 있습니다.

>>> os.getenv('API_KEY') is None
True
>>> os.getenv('API_KEY', 'abc')
'abc'

환경 변수 설정

그러면 새로운 환경 변수는 어떻게 설정할 수 있을까요?

환경 변수는 운영 체제에 따라서 약간씩 상이한 방법으로 설정할 수 있는데요. 운영 체제마다 환경 변수를 설정을 위해 제공하는 명령어가 다르기 때문입니다.

대표적으로 Unix 계열에서는 export 명령어, Windows 계열에서는 SET 명령어가 사용되는데요. 저는 Unix 계열인 MacOS를 사용하기 때문에 다음과 같이 API_KEY 환경 변수의 값을 abc로 설정해주겠습니다.

$ export API_KEY=abc
$ python
Python 3.11.2 (main, Apr  7 2023, 15:52:33) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getenv('API_KEY')
'abc'

이렇게 운영 체제의 명령어를 이용하여 환경 변수를 설정하면 터미널 창을 닫을 때까지 유지되는데요. 따라서 해당 프로그램을 종료하고 다시 실행하더라도 동일한 환경 변수 값을 얻을 수 있습니다.

$ python
Python 3.11.2 (main, Apr  7 2023, 15:52:33) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getenv('API_KEY')
'abc'

또 다른 방법으로는 프로그램을 실행할 때 python 명령어 앞에 환경 변수를 키=값 형태로 붙여줄 수도 있습니다.

$ API_KEY=def python
Python 3.11.2 (main, Apr  7 2023, 15:52:33) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getenv('API_KEY')
'def'

이 경우, 운영체제 수준에서 설정해준 환경 변수의 값이 무시되고 새로운 값으로 덮어써지는 것을 볼 수 있습니다.

사실 os.environ는 사전이기 때문에 받드시 이렇게 프로그램 실행 시점이나 실행 이전에 설정해줘야 하는 것은 아닙니다. 프로그램 내에서 얼마든지 새로운 환경 변수를 설정하거나 기존에 설정된 환경 변수의 값을 자유롭게 갱신 또는 제거할 수 있습니다.

>>> os.environ["API_KEY"] = 'xyz'
>>> os.environ["API_KEY"]
'xyz'
>>> os.getenv("API_KEY", 'abc')
'xyz'

주의 사항

os 모듈에는 새로운 환경 변수를 추가해주는 putenv()나 기존 환경 변수를 제거해주는 unsetenv()와 같은 함수들도 있는데 매우 주의해서 사용해야 합니다. 왜냐하면 이러한 함수들로 운영 체제 상의 환경 변수를 변경하였더라도, os 모듈이 최초 임포트될 때 이미 세팅되었던 os.environ에는 반영이 되지 않기 때문입니다. 따라서 이렇게 환경 변수를 조작하는 함수를 직접 사용하는 것 보다는 os.environ를 통해서 마치 사전 다루듯이 환경 변수를 추가/제거 하는 것이 더 안전 합니다. 무엇보다 맨 처음에 설명드린 환경 변수의 용도를 생각해보면 대부분 환경 변수는 애플리케이션 수준에서는 읽기 전용으로 쓰이는 것이 대부분일 것입니다.

전체 코드

본 포스팅에서 제가 작성한 전체 코드는 아래에서 직접 확인하고 실행해보실 수 있습니다.

https://dales.link/m4k

마치면서

지금까지 파이썬에 내장된 os 모듈을 통해 환경 변수를 어떻게 읽고 쓰는지에 대해서 살펴보았습니다. os 내장 모듈에 대한 좀 더 자세한 내용은 파이썬 공식 레퍼런스: os — Miscellaneous operating system interfaces를 참고해보시면 좋을 것 같습니다.