언어적 특징

  • 인터프리터(Interpreter) 언어로 별도의 컴파일 없이 실행된다.

  • 별도로 타입 명시를 하지 않으며, 실행 중에 타입이 변경 가능(Dynamically typed)하다. 

  • 객체 지향적(Object-oriendted) 언어로, 접근 제한자를 가지지 않지만 네이밍(Naming)의 언더스코어(_)로 접근 제한을 구분한다.

    • 이름 맨 앞에 언더스코어 1개이면 protected, 2개이면 private 이며, 그 외는 public 으로 구분한다.

  • 함수(function)와 클래스(class)는 일급 객체(The first-class objects)로, 모든 변수(매개변수, 로컬변수 등)에 할당 가능하며 일반적으로 다른 객체에 적용 가능한 연산을 모두 지원한다.

  • PYTHONPATH인터프리터가 파이썬 프로그램이 실행될 때 import된 모듈들이 실제 디스크에 어디에 위치했는지 알기 위해 사용하는 환경변수. 따라서 프로그램이 내장 모듈에 대해 ImportError 를 일으키면 가장 먼저 살펴봐야하는 부분이다.

  • PEP는 Python Enhancement Proposal의 약자로, 가독성 높은 파이썬의 코딩 스타일 중 하나이며, PEP8이 대중적이다.

  • 주석은 # comment""" comment """ 가 있는데, 후자는 docstring 용도로 사용된다.

    • 참고: Docstrings are not actually comments, but, they are documentation strings. These docstrings are within triple quotes. They are not assigned to any variable and therefore, at times, serve the purpose of comments as well.

  • 파이썬 인터프리터에서는 help() 와 dir() 이라는 함수를 사용할 수 있는데, 라이브러리를 잘 모를 경우 굉장히 유용하다.

    • The help() function is used to display the documentation string and also facilitates you to see the help related to modules, keywords, attributes, etc.

    • The dir() function is used to display the defined symbols. (클래스의 어떤 메소드가 있는지 확인할 때 매우 편하다.)

  • 파이썬 패키지(package)는 여러 모듈을 포함하는 네임스페이스의 집합이다. 최상위 패키지 디렉토리 안에 패키지 디렉토리가 있을 수 있는데 이들 안에 __init__.py 를 작성하면 해당 디렉토리 패키지임을 명시하는 것이다. 따라서 다른 디렉토리에서 다음과 같이 해당 모듈을 사용할 수 있다.

"""
예시: from 패키지명 import 모듈명

~/mypkg $ tree
.
├── utils
│   └── __init__.py
│   └── mini_module.py
│   └── large_module.py
└── subpkg
    ├── __init__.py
    └── new_module.py

mypkg 를 상위 디렉터리로 하고 위와 같은 구조를 가질 때,
subpkg의 new_module.py에서는 아래의 형태로 utils 의 모듈을 사용할 수 있다.
"""

from utils import mini_moudle
from utils.mini_module import *
from utils.large_moudle import MyObject

 

메모리 관리

  • 파이썬은 내부적(C언어로 작성되었음)으로 PyObject 라는 객체를 생성해서 데이터를 관리하는데, 데이터들은 Python Private Heap Space 라는 곳에 저장된다. 일반적으로 지역 변수는 스택에 저장된다고 배웠으나, 곧 살펴볼 파이썬의 내장 타입들은 모두 객체이며 힙 영역에 저장된다.

>>> a = 1
>>> type(a)
<class 'int'>
  • Private Heap 은 파이썬이 스스로 관리하는 곳이기 때문에 파이썬 코드로는 프로그래머가 직접적으로 메모리를 할당하거나 해제할 수 없다. 직접 살펴보고 싶다면 파이썬 C 라이브러리를 사용해야 한다.

  • PyObject는 멤버로 참조 카운트(reference count)를 가지는데, 이는 객체가 참조될 때 1씩 증가하고 참조되지 않을 경우 1씩 감소한다. 그리고 reference count = 0 이 되면 메모리는 해제된다.
    • sys 모듈의 getrefcount() 함수를 이용해서 count를 직접 확인해볼 수 있다.

    • 아래의 첫 출력 결과가 2인 것은 sys.getrefcount() 함수의 인자로 참조되었기 때문에 1이 아니라 2로 출력되는 것이다.

>>> import sys
>>> a = []
>>> sys.getrefcount(a)
2
>>> b = a
>>> sys.getrefcount(a)
3
>>> del a
>>> sys.getrefcount(b)
2
  • 그러나, 아래와 같이 순환 참조(Circular References)가 발생할 경우 레퍼런스 카운팅 기법으로는 메모리를 관리할 수 없다.

    • 순환 참조란 서로 다른 객체가 서로를 참조하는 경우를 의미한다. 여기서 두 객체가 삭제될 경우 참조 횟수는 0보다 큰 상태이지만 객체를 이미 삭제해버려서 해당 객체들에 접근할 수 없다는 문제가 발생한다.

>>> class Obj:
...     def __init__(self):
...         print('Hello,', id(self))
...
...     def __del__(self):
...         print('Bye,', id(self))
...
>>> o1 = Obj()
Hello, 4470886656
>>> o2 = Obj()
Hello, 4470654432
>>> sys.getrefcount(o1)
2
>>> sys.getrefcount(o2)
2
>>> dir() # 선언한 클래스와 생성된 인스턴스가 네임스페이스에 존재한다.
['Obj', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__',
'__package__', '__spec__', 'o1', 'o2']
>>> o1.x = o2
>>> o2.x = o1
>>> sys.getrefcount(o1)
3
>>> sys.getrefcount(o2)
3
>>> del o1 # o2.x 로 참조되므로 o1의 reference count = 1
>>> del o2 # o1.x 로 참조되므로 o2의 reference count = 1
>>> dir() # 삭제되었기 때문에 네임 스페이스에는 없으나 실제로 __del__() 메소드는 호출되지 않았다.
['Obj', '__annotations__', '__builtins__', '__doc__', '__loader__', '__name__',
'__package__', '__spec__']
  • 순환 참조와 같은 이슈를 해결하기 위해 파이썬은 가비지 콜렉터(Garbage Collector) 기능을 제공한다. 가비지 콜렉터는 gc 모듈을 import 해서 수동으로 관리할 수 있지만 파이썬에서는 자동으로 관리할 것은 권장한다.

  • 가비지 콜렉팅은 다음과 같이 동작한다.

    • 0~2세대로 객체들을 구분(이를 Generational Garbage Collecting 이라 한다.)하는데, 처음 객체가 생성되면 0세대로 분류된다. 그리고 각 세대별로 저장된 객체가 임계값(threshold, 최대로 저장할 객체의 개수)에 이르면 쓰레기 수집(collect)이 진행된다.

    • 한 번 수집기가 실행될 때마다 해당 프로그램은 중단되므로 성능에 큰 영향을 미친다.

    • 수집기가 실행되고 각 세대별로 살아남은 객체는 다음으로 옮겨진다. 0세대에서 살아남은 객체는 1세대로, 1세대에서 살아남은 객체는 2세대로 옮겨진다.

    • 임계값은 세대마다 다르며, Generational Hypothesis(최근에 생성된 객체일수록 빨리 제거되며, 최근에 생성된 객체는 오래된 객체를 참조할 가능성이 적다는 가설)에 따라 0세대의 임계값이 가장 높다.

  • gc 모듈을 이용해서 임계값을 바꾸거나 쓰레기 수집 기능을 직접 실행할 수 있다.

    • 임계값 변경 함수: gc.set_threshold(threshold0[, threshold1[, threshold2]])

    • 쓰레기 수집 기능 함수: gc.collect()

>>> import gc
>>> gc.get_threshold()	# 0세대는 700, 1세대는 10, 2세대는 10개까지 보관한다.
(700, 10, 10)
>>> gc.get_count()	# 0세대는 71개의 객체가 있다.
(71, 0, 0)
>>> gc.collect()	# 순환 참조로 삭제되지 않았던 객체들이 삭제되었다.
Bye, 4470886656
Bye, 4470654432
4
>>> gc.get_count()
(22, 0, 0)
  • 그 외에 참조 카운트로 메모리를 관리하다보니 Global Interpreter Lock(이하 GIL) 과 관련된 이슈도 존재한다. GIL은 파이썬 인터프리터 전역에 락 변수(lock variable)를 설정해놓은 것으로, 멀티 쓰레딩 시 임계 영역(critical section)에서는 단일 쓰레드만이 실행되도록 한다.

    • 임계 영역이란 둘 이상의 쓰레드가 동시에 접근했을 때 프로그램의 실행에 critical 하게 영향을 줄 수 있는 부분을 뜻한다.

    • 한 프로세스에서 실행중인 쓰레드들은 스택(+레지스터)을 제외한 나머지 모든 영역을 공유한다.

  • GIL 을 도입한 이유는 파이썬의 모든 객체가 힙에 저장되다 보니 멀티쓰레딩 환경에서 reference count 변수에 경쟁 조건(race condition)이 발생하는 것을 막기 위해서이다. 만약 reference count 변수를 멤버로 가지는 파이썬 객체마다 락 변수를 걸게 되면 데드락(deadlock)이 발생할 수 있으며 성능에 좋지 않기 때문에 파이썬 인터프리터 전역적으로 막아버린 것이다. 즉, 파이썬에서 단일 쓰레드만이 특정 객체 접근할 수 있도록 했다. 따라서 threading 모듈을 이용해서 멀티쓰레딩을 하더라도 실제로는 1개의 CPU가 여러 쓰레드를 번갈아가면서 실행시키다보니 컨텍스트 스위칭(context switching)이 빈번하게 발생하여 단일 쓰레드보다 성능이 떨어질 수 있다. (물론 이와 관련된 해결책으로 비동기 프로그래밍, 멀티프로세싱 등이 있는데 다음에 후술하겠다.)

 

Built-in Types

  • Integers

  • Floating-point

  • Complext numbers

  • Strings

  • Boolean

  • Built-in functions: 파이썬 인터프리터에 내장된 함수들로 위에서 설명했던 help()와 dir()이 이에 해당된다. 별도의 모듈을 import하지 않고 사용가능하다.

    • type() vs isinstance(): 파이썬의 데이터들은 모두 객체로 저장되지만, 내장형 타입(표준 데이터 타입)을 검사하기 위해 type(변수명) 함수를 사용하고 커스텀 클래스로 만든 객체들은 isinstance(변수명, 클래스명)로 클래스 타입을 검사한다. 즉, 파이썬 환경에서 인스턴스(=객체)와 내장형 타입을 구분하기 위해 제공하는 함수라고 볼 수 있다. 물론 표준 데이터 타입에 대해서도 isinstance 함수를 사용할 수 있다. 예를 들어, x = 1; isinstance(x, int); 의 출력 결과는 True 이다.

  • 내장형 타입 관련 연산

  • 비교 연산자

    • 파이썬에서는 직접 변수의 값을 비교할 때는 == 연산자를 사용하지만, 메모리 주소를 비교할 때(=동일 객체인지 등)는 is 연산자를 사용한다. 변수에 저장된 메모리 주소를 확인하려면 id(변수명) 함수를 사용하면 된다.

>>> a = 1000
>>> b = 1000
>>> a == b
True
>>> a is b
False
>>> id(a), id(b)
(4398724144, 4398724176)

 

 

텍스트파일에서 가장 빈도수가 많은 단어 출력

name = input('Enter file:')
handle = open(name)

di = dict()
for line in handle:
    words = line.split()
    for word in words:
        di[word] = di.get(word,0) + 1

largest = -1
theword = None
for name, count in di.items() :
    if count > largest : 
        largest = count
        theword = name
        
print('Done', theword, largest)

 

딕셔너리 정렬

- 먼저, 튜플의 특성: 불변 속성, 여러 값끼리 한 번에 비교 가능, 딕셔너리 .item() 메소드는 (키,값) 쌍인 튜플의 리스트를 반환

(0, 1, 2) < (5, 1, 2)
# True
(0, 1, 2000000) < (0, 3, 4)
# True
( 'Jones', 'Sally' ) < ('Jones', 'Sam')
# True
( 'Jones', 'Sally') > ('Adams', 'Sam')
# True

- 키를 기준으로 정렬

d = {'b':1, 'a':10, 'c':22}
d.items()
# dict_items([('b', 1), ('a', 10), ('c', 22)])
sorted(d.items())
# [('a', 10), ('b', 1), ('c', 22)]

# OR

for k, v in sorted(d.items()):
    print(k, v)
# a 10
# b 1
# c 22

- 값을 기준으로 정렬

c = {'a':10, 'b':1, 'c':22}
tmp = list()
for k, v in c.items() :
    tmp.append( (v, k) )

print(tmp)	# [(10, 'a'), (1, 'b'), (22, 'c')]
tmp = sorted(tmp)
print(tmp)	# [(1, 'b'), (10, 'a'), (22, 'c')]


# 내림차순을 원할 경우
# tmp = sorted(tmp, reverse=True)

- 리스트 컴프리헨션 (List Comprehension)

c = {'a':10, 'b':1, 'c':22}
print( sorted( [ (v,k) for k,v in c.items() ] ) )
# [(1, 'b'), (10, 'a'), (22, 'c')]

 

가장 많이 등장한 단어 Top 10 출력

fhand = open('test.txt')
counts = {}	# "단어:빈도수" 인 딕셔너리
for line in fhand:
    words = line.split()
    for word in words:
        counts[word] = counts.get(word, 0 ) + 1

for val, key in sorted([ (v, k) in counts.items() ], reverse=True):
    print(key, val)

 

 

 

[번역글]

https://m.blog.naver.com/passion053/221079317719

 

파이썬 입문자가 알면 좋은 유려한 기능 10선

* 이하의 내용은 10 Neat Python Tricks Beginners Should Know 의 글을 직접 번역한 것입니다. * 예...

blog.naver.com

https://m.blog.naver.com/PostView.nhn?blogId=passion053&logNo=221112010085&proxyReferer=https%3A%2F%2Fwww.google.com%2F

 

효율적인 성능, 메모리, 사용성을 위한 파이썬 코드 사례

* 이하의 내용은 Python Practices for Efficient Code: Performance, Memory, and Usability 의 글...

blog.naver.com

https://m.blog.naver.com/passion053/221058266968

 

파이썬의 유용한 기능들

* 이하의 내용은 Advanced Python Features 의 글을 직접 번역한 것입니다. * 제가 번역한 것을 다른곳...

blog.naver.com

 

파이썬 class 기본 메소드

https://corikachu.github.io/articles/python/python-magic-method

 

파이썬 더블 언더스코어: Magic Method | Corikachu

파이썬에서 __를 달고있는 메소드들에 대해서 살펴봅시다.

corikachu.github.io

 

파이썬 메모리 관리

https://b.luavis.kr/python/python-malloc

 

Luavis' Dev Story - Python의 메모리 할당

Python이 메모리를 할당하고 관리하는 방법

b.luavis.kr

https://www.evanjones.ca/memoryallocator/

 

Improving Python's Memory Allocator

Improving Python's Memory Allocator Evan Jones <ejones@uwaterloo.ca> http://evanjones.ca/ [PDF version] Abstract Python automatically manages memory using reference counting. In order to provide good performance for typical programs, Python provides its ow</ejones@uwaterloo.ca>

www.evanjones.ca

 

쓰레드 관련

https://dgkim5360.tistory.com/entry/understanding-the-global-interpreter-lock-of-cpython

 

왜 Python에는 GIL이 있는가

Python 사용자라면 한 번 쯤은 들어봤을 (안 들어봤다 해도 괜찮아요) 악명 높은 GIL (Global Interpreter Lock)에 대해 정리해본다. Global Interpreter Lock 그래서 GIL은 무엇인가? Python Wiki에서는 이렇게..

dgkim5360.tistory.com

 

비동기 프로그래밍

https://mingrammer.com/translation-asynchronous-python/

 

[번역] 비동기 파이썬

Asynchronous Python을 번역한 글입니다. 파이썬에서의 비동기 프로그래밍은 최근 점점 더 많은 인기를 끌고있다. 비동기 프로그래밍을 위한 파이썬 라이브러리는 많다. 그

mingrammer.com


원본 출처


장고(Django)는 웹 애플리케이션을 만들기 위한 파이썬 기반의 프레임워크로, 튼튼하며, 오픈 소스이다. 장고의 인기는 지난 2년 동안 증가해왔고, 이미 성숙한 단계에 있으며, 실제로 큰 규모의 단체들에게 이용되어진다.

웹 애플리케이션을 제작하기 위한 다른 파이썬 기반의 프레임워크들(Flask, Pyramid) 중에서도 장고는 가장 인기가 많다. 장고는 파이썬 버전 2.7과 3.6을 모두 지원한다. 이 글을 쓰는 시점에서 파이썬 2.7은 커뮤니티, third party packages, 그리고 온라인 문서화의 측면에서 여전히 이용가능한 버전이다. 장고는 적절하게 사용되면 안전하고, 높은 차원의 유연성을 제공한다. 바로 다음 내용이 파이썬을 사용한 서버 사이드 애플리케이션을 개발할 때 더 나아갈 수 있는 방법이다.

한 사람의 숙력된 파이썬 그리고 장고 개발자로써, 장고 설정(setup)에 대해 내가 몇 년동안 배우고 모아왔던 몇 가지 최고의 실행 방법을 여러분들과 공유할 것이다. 당신이 몇 개의 장고 프로젝트를 수행했는지, 혹은 이제 막 하나를 시작하는 단계인지와는 상관없이 여기에 기술된 방법들은 당신이 미래에 더 나은 애플리케이션을 만들도록 도와줄 것이다.

나는 당신들이 몇몇 툴들을 당신만의 개발 도구상자에 즉시 추가할 수 있도록 매우 실용적인 마음으로 이 글을 썼다. 당신은 심지어 다음 프로젝트를 위해 직접 제작한, 더욱 발전된 형태의 장고 표준 문서를 만들 수도 있다.

이 글의 목적을 위해, 당신이 리눅스 우분투(Linux Ubuntu)를 사용하고 있다고 가정한다.
글에서, $ 기호로 시작하는 1줄짜리 코드들은 해당 줄이 터미널에서 입력되어 져야 한다는 것을 강조하기 위한 것이다. 복붙할 때 $ 기호는 제외하라.


(자, 레쓰게릿)



Virtual Environment

파이썬 기반의 애플리케이션을 개발하는 과정에서, 지속적으로 third party package를 이용해왔다. 이러한 패키지들은 자주 업데이트되어지므로, 패키지들을 지속적으로 준비하는 것이 필수이다. 하나의 로컬 컴퓨터에서 다수의 프로젝트를 개발할 때, 각 패키지의 현 버전의 트랙(track)을 유지하는 것이 문제이다. 그 이유는 다른 프로젝트에서 같은 패키지의 다른 버전을 사용하는 것이 불가능하기 때문이다. (프로젝트 A에서 패키지 P의 1.2 버전을 사용하는데, 프로젝트 B에서 패키지 P의 1.4버전을 사용할 수 없다.) 게다가, 한 프로젝트에서 패키지를 업데이트하는 것이 다른 프로젝트에서 하나 또는 여러 개의 기능(functionality)의 역할을 하는 패키지들을 멈추게 할 수도 있다.

이런 문제는 가상 환경을 통해 해결될 수 있다. 직접 가상 환경(Virtual Environment)을 설정해보자.

우선 가상환경을 설치하라.

$ apt-get update
$ apt-get install python-pip python-dev build-essential

$ export LC_ALL="en_US.UTF-8" # 다음 줄에서 에러가 뜰 경우 쉘 환경 변수를 등록하라.

$ pip install --upgrade pip
$ pip install --upgrade virtualenv
$ mkdir ~/.virtualenvs
$ pip install virtualenvwrapper
$ export WORKON_HOME=~/.virtualenvs
$ nano ~/.bashrc



~/.bashrc 의 파일 끝에 아래 줄을 추가하라.

. /usr/local/bin/virtualenvwrapper.sh

(반드시 해당 경로에 해당 파일이 있는지 확인한 후 추가하세요.)
(만약 파일이 없다면, find / -name "virtualenvwrapper.sh" 명령어로 경로를 찾길 바랍니다.)


실행하라.

$ . .bashrc


설치가 끝나면, 프로젝트이름을 타이핑해서 새 가상 환경을 만들어라.

$ mkvirtualenv project_name


가상 환경에 있는 동안은 터미널에서 아래처럼 접두사가 추가된다는 것을 볼 것이다.

(project_name) ofir@playground:~$


가상 환경을 나가기 위해선 아래의 명령어를 사용하라. 이 명령어로 인해 로컬 컴퓨터의 실제 파이썬 컨텍스트로 되돌아 간다.

$ deactivate


특정 가상 환경 컨텍스트를 시작하려면 아래의 명령어를 사용하라.

$ workon project_name


본인의 로컬 머신에 존재하는 가상 환경들의 목록을 보려면 아래의 명령어를 사용하라.

$ lsvirtualenv


로컬 컴퓨터의 가상환경에서 프로젝트 의존성을 갖는 것은 분리된 환경에서 패키지들을 유지하도록 한다. 즉, 하나 또는 다수의 프로젝트만을 위해 특정 패키지들을 사용한다. 새 가상환경을 만들 때, 당신은 설치된 패키지 없이 완전히 새로운 가상환경에서 시작할 것이다. 그 때는 다른 가상환경에 있는 프로젝트와 동일한 패키지를 설치하더라도 다른 버전을 사용할 수 있다.

장고 설치를 예로 들면,

(project_name) $ pip install Django==1.11

(현재 장고 최신 버전은 2.0.5)

위에서 설치한 장고 1.11 버전은 오직 그 환경(여기선 project_name)에서만 이용가능한 것이다. 당신의 주요 파이썬 인터프리터 또는 로컬 컴퓨터의 다른 가상 환경 모두 당신이 그 환경에서 설치했던 새로운 장고 패키지에는 접근할 수 없을 것이다.

가상 환경을 이용하여 서버를 실행하는 명령을 사용하기 위해, 가상환경의 컨텍스트에서 아래와 같은 명령어를 사용하라.

(project_name) $ cd /path/to/django/project
(project_name) $ ./manage.py runserver


마찬가지로, 가상환경에서 파이썬 인터프리터에 들어가려면,

(project_name) $ python

이미 그 환경에서 설치된 패키지들을 이용할 수 있다.




Requirements

Requirements는 프로젝트에서 사용중인 파이썬 패키지의 목록으로, 각 패키지마다 이름버전이 함께 기록되어 있다.

아래는 requirements.txt 파일의 예시이다.

dicttoxml==1.7.4
Django==1.11.2
h5py==2.7.0
matplotlib==2.0.2
numpy==1.13.0
Pillow==4.1.1
psycopg2==2.7.1
pyparsing==2.2.0
python-dateutil==2.6.0
pytz==2017.2
six==1.10.0
xmltodict==0.11.0


requirements.txt 파일을 최신으로 유지하는 것은 다른 개발자들과 적절히 협업하는 데 있어 필수적이다. 또한 당신의 배포 환경을 적절하게 설정하는 것도 중요하다. 이 파일이 Code Repository 에 포함되어 있으면, 단 한 줄만 터미널에 입력하면 가상 환경에서 설치된 모든 패키지들을 업데이트할 수 있다. 그 때는 매우 짧은 시간에 실행하므로, 함께 일할 개발자를 깨울 수 있다.

requirements.txt 파일을 생성하거나 기존의 것을 갱신하기 위해, 가상환경 내에서 아래와 같은 명령어를 사용하라.

(project_name) $ pip freeze > requirements.txt


당신의 편리함을 위해, 이 명령어가 Git 저장소에 의해 트랙되어진 폴더에서 실행하는지 확인하라. 이는 다른 코드의 인스턴스가 requirements.txt 파일에 접근하는 것을 가능하게 한다.

만약 새 개발자가 팀에 합류하면, 또는 당신이 requirements.txt 파일에 기록된 동일한 패키지를 사용하는 새 환경을 설정하길 원한다면, 가상 환경 컨텍스트에서 아래의 명령어를 실행하라.

(project_name) $ cd /path/to/requirements/file
(project_name) $ pip install -r requirements.txt


파일에 기록된 모든 요구사항은 즉시 당신의 가상환경에 설치될 것이다. 오래된 버전들은 갱신될 것이고, 새로운 버전들은 파일의 요구사항에 정확히 맞추고자 다운그레이드(downgrade)될 것이다. 당신이 여전히 유지하길 원하는 환경들 사이에서 차이가 있을지도 모른다는 것에 주의하라!

나는 당신의 Work flow에 이 명령어들을 통합하는 것을 적극 추천한다. 저장소에 코드를 push 하기 전에 requirements.txt 파일을 갱신하라. 그리고 저장소로부터 코드를 pull한 후에 requirements.txt 파일을 설치하라.




Better settings.py configuration

장고는 매우 기본적이고 유용한 settings.py 파일을 즉시 사용할 수 있다. (즉, 기본적으로 제공한다는 소리) 이 파일은 당신의 프로젝트에서 메인이 되고, 매우 유용한 설정들을 정의한다. 또한 매우 간단하다. 다만 가끔, 개발자가 팀에서 일할 때, 배포 환경을 설정할 때, 혹은 당신이 기본으로 제공되는 settings.py 파일을 둘 이상 필요로 할 때 등 다양한 설정 파일이 요구될 수 있다.

다수의 설정 파일들은 개별적으로 각 환경을 위해 쉽게 사용자가 맞춤형으로 설정할 수 있게 한다. (여기서 환경은 위에서 언급한 가상 환경이 아닌, 실행 환경을 의미)

ALLOWED_HOSTS # for production environment
DEBUG
DATABASES # for different developers on the same team


settings.py 파일을 설정하기 위한 확장된 접근법을 제안하겠다. 이 방식은 당신이 다른 버전들을 유지하도록 해주고, 어떤 특정 시간과 특정 환경에서 원하는 패키지를 사용하도록 해준다.

첫번째, settings.py 파일 경로로 들어가라.

(project_name) $ cd /path/to/settings/file

(장고 프로젝트 폴더에 들어가면 project_name/settings.py 경로)

그 다음, settings 라는 이름의  새 모듈(=디렉토리)를 생성하라. 모듈은 __init__.py 파일을 포함하는 폴더이다.

(project_name) $ mkdir settings


settings.py 파일을 base.py 로 이름을 바꾸고 위에서 생성한 새 모듈(settings 폴더)로 그 파일을 옮겨라.

(project_name) $ mv settings.py settings/base.py


이 예시에서는, 당신이 개발환경과 배포환경만을 위한 하나의 settings 파일을 설정하길 원한다고 가정을 한다. 같은 팀 내 다른 개발자들은 다른 settings 파일을 정의하기 위해 정확히 동일한 방법을 사용할 수 있다.

개발 환경을 생성하라.

(project_name) $ nano settings/development.py


해당 파일 내에 아래와 같이 입력하라.

from .base import *

DEBUG = True


배포 환경을 생성하라.

(project_name) $ nano settings/production.py


해당 파일 내에 아래와 같이 입력하라.

from .base import *

DEBUG = False
ALLOWED_HOSTS = [‘app.project_name.com’, ]


이제는 당신이 구체적인 환경의 설정을 갱신하거나 추가하길 원할 때마다, 자신만의 settings 파일에서 쉽게 구현할 수 있다.

여러분들은 "장고는 각 환경에서 어떤 settings 파일을 로드할 지 어떻게 아는가"에 대해 궁금할 지도 모른다. 그것은 바로 __init__.py 파일이 이용되는 이유이다. 예를 들어, 서버를 실행할 때 로드하기 위해 장고가 settings.py를 찾을 때, 장고는 정확히 settings.py 파일 보다는 settings 모듈을 찾는다. 하지만 그 모듈이 __init__.py 파일을 포함해야만 장고가 그 모듈이 settings.py 파일과 같은 것이란 걸 알게 된다. 장고가 __init__.py 파일안에 무엇이 쓰여졌든지 그 파일을 로드해서 실행할 것이다.

그러므로, 우리는 어떤 settings 파일을 __init__.py 파일 안에 로드할 지를 정의할 필요가 있다.

(project_name) $ nano settings/__init__.py


파일 안에 아래와 같이 타이핑 하라. (배포 환경으로 설정할 경우)

from .production import *


이 방식에서, 장고는 매 실행마다 base.py와 production.py 를 모두 로드할 것이다.

이제 남은 유일한 설정은 당신의 .gitignore 파일에 __init__.py를 기록하는 것이다. 그래서 push와 pull을 할 때 포함되지 않게 한다. 일단 새 환경을 설정하면, settings 모듈에 새 __init__.py 파일을 생성하는 것을 잊지말라. 그 다음 전에 수행했던 것처럼 정확하게 요구되는 settings 파일을 임포트(import)하라.



끝으로,

이 글에서는 우리는 장고 프로젝트를 더 효율적으로 설정하기 위한 세 가지 (베스트) 실행 방식을 다루어보았다.

  1. 가상환경에서 작업하는 것

  2. 워크플로우에서 지속적으로 requirements.txt를 이용하고, 파일을 최신의 것으로 유지하는 것

  3. settings 모듈을 사용하여 설정하는 것



'Programming Language > Python' 카테고리의 다른 글

[정리 03] 유용한 기능들  (0) 2021.02.05
[정리 02] 표준 데이터 타입(Standard Data-Type)  (0) 2021.02.04
[정리 01] Python 기초  (0) 2021.02.04
간단한 알고리즘  (0) 2019.06.30
Tip (Reference)  (0) 2019.05.15

+ Recent posts