Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 263 – Python 소스 코드 인코딩 정의

Author:
Marc-André Lemburg <mal at lemburg.com>, Martin von Löwis <martin at v.loewis.de>
Status:
Final
Type:
Standards Track
Created:
06-Jun-2001
Python-Version:
2.3
Post-History:


Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 Python 소스 파일의 인코딩을 선언하는 구문을 도입할 것을 제안합니다. 그런 다음 Python 파서는 인코딩 정보를 사용하여 지정된 인코딩으로 파일을 해석합니다. 특히 이는 소스 코드의 유니코드 리터럴 해석을 향상하며, 유니코드를 인식하는 편집기에서 UTF-8 등의 인코딩을 직접 사용하여 유니코드 리터럴을 작성할 수 있게 합니다.

문제

Python 2.1에서는 유니코드 리터럴을 Latin-1 기반 인코딩인 “unicode-escape”를 사용해야만 작성할 수 있습니다. 이로 인해 많은 아시아 국가처럼 Latin-1이 아닌 로캘에서 생활하고 작업하는 Python 사용자에게 프로그래밍 환경이 매우 불친절해집니다. 프로그래머는 원하는 인코딩을 사용하여 8비트 문자열을 작성할 수 있지만, 유니코드 리터럴에는 “unicode-escape” 인코딩을 사용해야 합니다.

제안된 해결책

파일 상단의 특수 주석을 사용하여 인코딩을 선언함으로써 Python 소스 코드 인코딩을 소스 파일별로 표시하고 변경할 수 있도록 할 것을 제안합니다.

Python이 이 인코딩 선언을 인식하도록 하려면 Python 소스 코드 데이터의 처리 방식과 관련하여 몇 가지 개념 변경이 필요합니다.

인코딩 정의

다른 인코딩 힌트가 제공되지 않으면 Python은 ASCII를 표준 인코딩으로 사용합니다.

소스 코드 인코딩을 정의하려면 다음과 같이 파일의 첫 번째 줄 또는 두 번째 줄에 매직 주석을 소스 파일에 배치해야 합니다.:

# coding=<encoding name>

또는(널리 사용되는 편집기가 인식하는 형식을 사용하는 경우):

#!/usr/bin/python
# -*- coding: <encoding name> -*-

또는:

#!/usr/bin/python
# vim: set fileencoding=<encoding name> :

더 정확히 말하면 첫 번째 줄 또는 두 번째 줄은 다음 정규 표현식과 일치해야 합니다.:

^[ \t\f]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)

그런 다음 이 표현식의 첫 번째 그룹이 인코딩 이름으로 해석됩니다. Python이 인코딩을 알 수 없으면 컴파일 중에 오류가 발생합니다. 인코딩 선언이 포함된 줄에는 Python 문이 있어서는 안 됩니다. 첫 번째 줄이 일치하면 두 번째 줄은 무시됩니다.

Windows와 같이 유니코드 파일의 시작 부분에 유니코드 BOM 표시를 추가하는 플랫폼을 지원하기 위해 UTF-8 시그니처 \xef\xbb\xbf는 매직 인코딩 주석이 지정되지 않은 경우에도 ‘utf-8’ 인코딩으로 해석됩니다.

소스 파일에서 UTF-8 BOM 표시 시그니처와 매직 인코딩 주석을 모두 사용하는 경우 주석에 허용되는 유일한 인코딩은 ‘utf-8’입니다. 다른 인코딩을 사용하면 오류가 발생합니다.

예제

다음은 Python 소스 파일의 상단에서 소스 코드 인코딩을 정의하는 다양한 방식을 명확히 보여 주는 몇 가지 예입니다.

  1. 인터프리터 바이너리를 사용하고 Emacs 스타일 파일 인코딩 주석을 사용하는 경우:
    #!/usr/bin/python
    # -*- coding: latin-1 -*-
    import os, sys
    ...
    
    #!/usr/bin/python
    # -*- coding: iso-8859-15 -*-
    import os, sys
    ...
    
    #!/usr/bin/python
    # -*- coding: ascii -*-
    import os, sys
    ...
    
  2. 인터프리터 줄 없이 일반 텍스트를 사용하는 경우:
    # This Python file uses the following encoding: utf-8
    import os, sys
    ...
    
  3. 텍스트 편집기마다 파일 인코딩을 정의하는 방식이 다를 수 있습니다. 예를 들면 다음과 같습니다.:
    #!/usr/local/bin/python
    # coding: latin-1
    import os, sys
    ...
    
  4. 인코딩 주석이 없으면 Python 파서는 ASCII 텍스트로 가정합니다.:
    #!/usr/local/bin/python
    import os, sys
    ...
    
  5. 작동하지 않는 인코딩 주석:
    1. “coding:” 접두사가 없습니다.:
      #!/usr/local/bin/python
      # latin-1
      import os, sys
      ...
      
    2. 인코딩 주석이 1행이나 2행에 없습니다.:
      #!/usr/local/bin/python
      #
      # -*- coding: latin-1 -*-
      import os, sys
      ...
      
    3. 지원되지 않는 인코딩입니다.:
      #!/usr/local/bin/python
      # -*- coding: utf-42 -*-
      import os, sys
      ...
      

개념

이 PEP는 이러한 매직 주석을 사용할 수 있도록 구현해야 하는 다음 개념을 기반으로 합니다.

  1. 전체 Python 소스 파일은 하나의 인코딩을 사용해야 합니다. 서로 다른 인코딩으로 인코딩된 데이터를 삽입하는 것은 허용되지 않으며, Python 소스 코드 컴파일 중 디코딩 오류가 발생합니다.

    위에서 설명한 방식으로 처음 두 행을 처리할 수 있는 모든 인코딩을 소스 코드 인코딩으로 사용할 수 있으며, 여기에는 ASCII 호환 인코딩과 Shift_JIS 같은 일부 멀티바이트 인코딩이 포함됩니다. 예를 들어 UTF-16처럼 모든 문자에 2바이트 이상을 사용하는 인코딩은 포함되지 않습니다. 이는 토크나이저의 인코딩 감지 알고리즘을 단순하게 유지하기 위해서입니다.

  2. 이스케이프 시퀀스 처리는 현재와 같은 방식으로 계속 작동해야 하지만, 가능한 모든 소스 코드 인코딩에서 적용되어야 합니다. 즉, 표준 문자열 리터럴(8비트 문자열과 유니코드 문자열 모두)에는 이스케이프 시퀀스 확장이 적용되는 반면, 원시 문자열 리터럴에서는 매우 작은 부분 집합의 이스케이프 시퀀스만 확장됩니다.
  3. Python의 토크나이저와 컴파일러 조합은 다음과 같이 작동하도록 업데이트해야 합니다.
    1. 파일을 읽습니다.
    2. 파일별로 고정된 인코딩을 가정하여 유니코드로 디코딩합니다.
    3. 이를 UTF-8 바이트 문자열로 변환합니다.
    4. UTF-8 콘텐츠를 토큰화합니다.
    5. 이를 컴파일합니다. 주어진 유니코드 데이터에서 유니코드 객체를 만들고, 유니코드 리터럴 데이터에서 문자열 객체를 만들 때는 먼저 주어진 파일 인코딩을 사용하여 UTF-8 데이터를 8비트 문자열 데이터로 다시 인코딩합니다.

Python 식별자는 인코딩의 ASCII 부분 집합으로 제한되므로 4단계 이후에는 추가 변환이 필요하지 않습니다.

구현

현재 인코딩을 선언하지 않고 문자열 리터럴에서 ASCII가 아닌 문자를 사용하는 기존 코드와의 하위 호환성을 위해 구현은 두 단계로 도입됩니다.

  1. 문자열 리터럴과 주석에서 비ASCII 문자를 허용하며, 내부적으로 누락된 인코딩 선언을 “iso-8859-1” 선언으로 취급합니다. 이렇게 하면 처리 과정의 2단계와 5단계 사이에서 임의의 바이트 문자열이 올바르게 왕복 변환되며, ASCII가 아닌 바이트를 포함하는 유니코드 리터럴에 대해 Python 2.2와의 호환성이 제공됩니다.

    입력에서 ASCII가 아닌 바이트가 발견되면 잘못 인코딩된 입력 파일마다 한 번씩 경고가 발생합니다.

  2. 경고를 제거하고 기본 인코딩을 “ascii”로 변경합니다.

내장 compile() API가 유니코드를 입력으로 허용하도록 개선됩니다. 8비트 문자열 입력에는 위에서 설명한 표준 인코딩 감지 절차가 적용됩니다.

코딩 선언이 포함된 유니코드 문자열을 compile()에 전달하면 SyntaxError가 발생합니다.

SUZUKI Hisao가 패치를 작업 중이며, 자세한 내용은 [2]를 참조하십시오. 1단계만 구현하는 패치는 [1]에서 사용할 수 있습니다.

단계

위 1단계와 2단계의 구현은 2.3에서 완료되었지만, 기본 인코딩을 “ascii”로 변경하는 작업은 제외되었습니다.

기본 인코딩은 2.5 버전에서 “ascii”로 설정되었습니다.

범위

이 PEP는 현재 (다소) 정의되지 않은 소스 코드 인코딩 상황에서 더 견고하고 이식성 있는 정의로 업그레이드할 수 있는 경로를 제공하고자 합니다.

참고 자료

이력

  • 1.10 이상: CVS 이력 참조
  • 1.8: 코딩 정규 표현식에 ‘.’을 추가함.
  • 1.7: 1단계 구현에 경고를 추가함. Latin-1 기본 인코딩을 인터프리터의 기본 인코딩으로 대체함. compile()에 사소한 수정을 추가함.
  • 1.4 - 1.6: 사소한 수정
  • 1.3: Martin v. Loewis의 의견을 반영함: UTF-8 BOM 마크 검출, Emacs 스타일 매직 주석, 2단계 구현 접근 방식