# 파이썬 개발 모드

버전 3.7에 추가.

파이썬 개발 모드에는 기본적으로 활성화하기에 너무 비싼 추가 실행 시간 검사를 도입합니다. 코드가 올바르면 기본값보다 더 상세하지(verbose) 않아야 합니다; 새로운 경고는 문제가 감지될 때만 발생합니다.

`-X dev` 명령 줄 옵션을 사용하거나 `PYTHONDEVMODE` 환경 변수를 `1`로 설정하여 활성화할 수 있습니다.

# 파이썬 개발 모드의 효과

파이썬 개발 모드를 활성화하는 것은 다음 명령과 유사하지만, 아래에 설명된 추가 효과가 있습니다:

    PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python3 -W default -X faulthandler

파이썬 개발 모드의 효과:

- `default` 경고 필터를 추가합니다. 다음과 같은 경고가 표시됩니다:

  - `DeprecationWarning`

  - `ImportWarning`

  - `PendingDeprecationWarning`

  - `ResourceWarning`

  일반적으로, 위의 경고는 기본 경고 필터가 필터링합니다.

  `-W default` 명령 줄 옵션이 사용된 것처럼 작동합니다.

  경고를 에러로 처리하려면 `-W error` 명령 줄 옵션을 사용하거나 `PYTHONWARNINGS` 환경 변수를 `error`로 설정하십시오.

- 메모리 할당자에 디버그 훅을 설치하여 다음을 확인합니다:

  - 버퍼 언더플로

  - 버퍼 오버플로

  - 메모리 할당자 API 위반

  - GIL의 안전하지 않은 사용

  `PyMem_SetupDebugHooks()` C 함수를 참조하십시오.

  `PYTHONMALLOC` 환경 변수가 `debug`로 설정된 것처럼 동작합니다.

  메모리 할당자에 디버그 훅을 설치하지 않고 파이썬 개발 모드를 사용하려면, `PYTHONMALLOC` 환경 변수를 `default`로 설정하십시오.

- 파이썬 시작 시 `faulthandler.enable()`을 호출하여 `SIGSEGV`, `SIGFPE`, `SIGABRT`, `SIGBUS` 및 `SIGILL` 시그널에 대한 처리기를 설치하여 충돌 시 파이썬 트레이스백을 덤프합니다.

  `-X faulthandler` 명령 줄 옵션이 사용되거나 `PYTHONFAULTHANDLER` 환경 변수가 `1`로 설정된 것처럼 작동합니다.

- asyncio 디버그 모드를 활성화합니다. 예를 들어, `asyncio`는 어웨이트 하지 않은 코루틴을 확인하고 이를 로그 합니다.

  `PYTHONASYNCIODEBUG` 환경 변수가 `1`로 설정된 것처럼 동작합니다.

- 문자열 인코딩과 디코딩 연산에 대해 encoding과 errors 인자를 확인합니다. 예: `open()`, `str.encode()` 및 `bytes.decode()`.

  기본적으로, 최상의 성능을 위해, errors 인자는 첫 번째 인코딩/디코딩 에러에서만 검사되며 빈 문자열에 대해서는 encoding 인자가 무시되는 경우가 있습니다.

- `io.IOBase` 파괴자는 `close()` 예외를 로그 합니다.

- `sys.flags`의 `dev_mode` 어트리뷰트를 `True`로 설정합니다.

파이썬 개발 모드는 (성능과 메모리에 대한) 오버헤드 비용이 너무 비싸서, 기본적으로 `tracemalloc` 모듈을 활성화하지 않습니다. `tracemalloc` 모듈을 활성화하면 일부 에러의 원인에 대한 추가 정보가 제공됩니다. 예를 들어, `ResourceWarning`은 자원이 할당된 곳의 트레이스백을 로그하고, 버퍼 오버플로 에러는 메모리 블록이 할당된 곳의 트레이스백을 로그 합니다.

파이썬 개발 모드는 `-O` 명령 줄 옵션이 `assert` 문을 제거하거나 `__debug__`를 `False`로 설정하는 것을 막지 않습니다.

버전 3.8에서 변경: `io.IOBase` 파괴자는 이제 `close()` 예외를 로그 합니다.

버전 3.9에서 변경: encoding과 errors 인자는 이제 문자열 인코딩과 디코딩 연산을 검사합니다.

# ResourceWarning 예

명령 줄에 지정된 텍스트 파일의 줄 수를 세는 스크립트의 예:

    import sys

    def main():
        fp = open(sys.argv[1])
        nlines = len(fp.readlines())
        print(nlines)
        # The file is closed implicitly

    if __name__ == "__main__":
        main()

스크립트는 파일을 명시적으로 닫지 않습니다. 기본적으로, 파이썬은 아무런 경고도 하지 않습니다. 269 줄이 있는 README.txt를 사용하는 예:

    $ python3 script.py README.txt
    269

파이썬 개발 모드를 사용하면 `ResourceWarning` 경고가 표시됩니다:

    $ python3 -X dev script.py README.txt
    269
    script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
      main()
    ResourceWarning: Enable tracemalloc to get the object allocation traceback

또한, `tracemalloc`을 활성화하면 파일이 열린 줄이 표시됩니다:

    $ python3 -X dev -X tracemalloc=5 script.py README.rst
    269
    script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
      main()
    Object allocated at (most recent call last):
      File "script.py", lineno 10
        main()
      File "script.py", lineno 4
        fp = open(sys.argv[1])

수선은 파일을 명시적으로 닫는 것입니다. 컨텍스트 관리자를 사용하는 예:

    def main():
        # Close the file explicitly when exiting the with block
        with open(sys.argv[1]) as fp:
            nlines = len(fp.readlines())
        print(nlines)

자원을 명시적으로 닫지 않으면 예상보다 오래 자원을 열어둘 수 있습니다; 파이썬을 종료할 때 심각한 문제가 발생할 수 있습니다. CPython에서도 나쁘지만, PyPy에서는 더 나쁩니다. 리소스를 명시적으로 닫으면 응용 프로그램을 더 결정적이고 안정적으로 만들 수 있습니다.

# 잘못된 파일 기술자 에러 예

자신의 첫 줄을 표시하는 스크립트:

    import os

    def main():
        fp = open(__file__)
        firstline = fp.readline()
        print(firstline.rstrip())
        os.close(fp.fileno())
        # The file is closed implicitly

    main()

기본적으로, 파이썬은 아무런 경고도 하지 않습니다:

    $ python3 script.py
    import os

파이썬 개발 모드는 `ResourceWarning`을 표시하고 파일 객체를 파이널라이즈 할 때 “잘못된 파일 기술자(Bad file descriptor)” 에러를 로그 합니다:

    $ python3 script.py
    import os
    script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
      main()
    ResourceWarning: Enable tracemalloc to get the object allocation traceback
    Exception ignored in: <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
    Traceback (most recent call last):
      File "script.py", line 10, in <module>
        main()
    OSError: [Errno 9] Bad file descriptor

`os.close(fp.fileno())`는 파일 기술자를 닫습니다. 파일 객체 파이널라이저가 파일 기술자를 다시 닫으려고 하면, `Bad file descriptor` 에러로 실패합니다. 파일 기술자는 한 번만 닫아야 합니다. 최악의 시나리오에서는, 두 번 닫을 때 충돌이 발생할 수 있습니다 (예는 bpo-18748을 참조하십시오).

수선은 `os.close(fp.fileno())` 줄을 제거하거나, `closefd=False`로 파일을 여는 것입니다.