[Final] PEP 278 - Universal Newline Support
원문 링크: PEP 278 - Universal Newline Support
상태: Final 유형: Standards Track 작성일: 14-Jan-2002
PEP 278 – 유니버설 뉴라인 지원
개요
이 PEP는 Python이 현재 플랫폼의 기본 줄바꿈 (newline) 형식이 아닌 파일에서도 I/O를 지원하는 방법을 제안합니다. 이를 통해 각 플랫폼의 Python은 CR (Macintosh), LF (Unix), 또는 CR LF (Windows) 줄바꿈을 가진 파일을 읽고 임포트(import)할 수 있게 됩니다.
오늘날 인터넷을 통해 다운로드된 파일, 다른 플랫폼의 원격 마운트된 파일 시스템, Mac OS X의 Mac 및 Unix 줄바꿈 이중 표준 등 현재 플랫폼의 표준과 일치하지 않는 줄바꿈을 가진 파일을 접하는 경우가 점점 더 많아지고 있습니다. 에디터 및 컴파일러와 같은 많은 도구는 이미 이러한 상황을 잘 처리하고 있으며, Python도 그렇게 하는 것이 좋습니다.
명세 (Specification)
유니버설 뉴라인 지원은 기본적으로 활성화되어 있지만, Python을 configure하는 동안 비활성화할 수 있습니다.
유니버설 뉴라인 지원이 활성화된 Python에서는 모든 import
문과 execfile()
호출에 이 기능이 자동으로 적용됩니다. eval()
또는 exec
에 대한 특별한 지원은 없습니다.
유니버설 뉴라인 지원이 활성화된 Python에서 open()
함수의 mode
매개변수는 “U”를 사용할 수 있습니다. 이는 “유니버설 뉴라인 해석을 사용하는 텍스트 파일로 입력용으로 열기”를 의미합니다. “rb”와의 대칭을 위해 “rU” 모드도 허용됩니다. “U” 모드는 “+”와 같은 다른 모드 플래그와 결합할 수 없습니다. 입력 파일의 모든 줄바꿈은 Python에서 \n
으로 인식되므로, 유니버설 뉴라인을 처리하기 위해 변경해야 할 다른 코드는 거의 없습니다.
줄바꿈 변환은 read()
, readline()
, readlines()
등 데이터를 읽는 모든 호출에서 발생합니다. 다른 줄바꿈 규칙으로 파일에 출력하는 것에 대한 특별한 지원은 없으므로, “wU” 모드도 허용되지 않습니다.
유니버설 뉴라인 모드로 열린 파일 객체는 파일에서 사용된 줄바꿈 규칙을 반영하는 새로운 속성 newlines
를 가집니다. 이 속성의 값은 None
(아직 줄바꿈을 읽지 않음), "\r"
, "\n"
, "\r\n"
중 하나이거나, 발견된 모든 줄바꿈 유형을 포함하는 튜플이 될 수 있습니다.
근거 (Rationale)
유니버설 뉴라인 지원은 Python이 아닌 C로 구현됩니다. 이는 다른 줄바꿈 규칙을 가진 파일도 임포트할 수 있도록 하기 위함입니다. 예를 들어, 원격 파일 시스템 연결을 통해 Python Lib
디렉터리를 공유하거나, Mac OS X에서 MacPython과 Unix-Python 간에 공유할 수 있게 하기 위함입니다. 이러한 목표를 달성하려면 유니버설 뉴라인 규칙이 성능에 미치는 영향이 합리적으로 작아야 하며, 이는 Python으로 구현할 경우 모든 임포트 작업이 느려질 수 있으므로 옵션이 될 수 없다는 것을 의미합니다. 또한 Visual C++ 및 기타 Windows 도구가 흔히 생성하는 여러 줄바꿈 규칙을 가진 파일 때문에, 파일에서 사용된 줄바꿈을 빠르게 확인하는 방식 (플랫폼 로컬 줄바꿈이 발견되면 임포트를 C 코드로 넘기는 방식)은 작동하지 않을 것입니다. 마지막으로, C 구현은 트레이스백(traceback) 등 (Python 소스 모듈을 여는) 처리도 쉽게 할 수 있게 합니다.
유니버설 뉴라인 출력 구현은 없습니다. Python 프로그램은 자체적으로 처리하거나 플랫폼 로컬 규칙으로 파일을 작성해야 합니다. 그 이유는 입력이 어려운 경우이고, 다른 줄바꿈을 파일에 출력하는 것은 Python에서 이미 충분히 쉽기 때문입니다.
또한, 놀랍게도 출력 구현은 입력 구현보다 훨씬 더 어렵습니다. 많은 출력이 PyXXX_Print()
메서드를 통해 이루어지며, 이 시점에서는 파일 객체를 사용할 수 없고 FILE *
만 사용할 수 있기 때문입니다. 따라서 출력 구현은 FILE*
에서 파일 객체로 어떤 식으로든 이동해야 하는데, 이는 현재 줄바꿈 구분 기호가 저장되는 곳이기 때문입니다.
입력 구현은 그러한 문제가 없습니다. Python 소스 트리에는 파일이 C에서 부분적으로 읽히고 Python에서 부분적으로 읽히는 경우가 없으며, 이러한 경우는 확장 모듈에서도 드물 것으로 예상됩니다. 이러한 경우가 존재한다면 유일한 문제는 fread()
또는 fgets()
호출이 C에서 직접 이루어질 때 파일 객체의 newlines
속성이 업데이트되지 않는다는 것입니다.
fp.write()
에 전달된 문자열이 fp.newlines
를 줄 종결자로 사용하도록 변환되지만 다른 모든 출력은 그렇지 않은 부분적인 출력 구현은 너무나 놀라운 일이라고 생각합니다.
유니버설 뉴라인에 대한 출력 지원이 없으므로, “rU+” 모드에 대한 지원도 없습니다. 이전 단락의 놀라움 요소가 훨씬 더 강하게 적용될 것입니다.
eval()
또는 exec
에 전달되는 문자열에는 유니버설 뉴라인 지원이 없습니다. 이러한 문자열은 항상 표준 \n
줄 바꿈을 가질 것으로 예상되며, 문자열이 파일에서 온 경우 해당 파일은 유니버설 뉴라인으로 읽을 수 있습니다.
유니코드와 관련하여 특별한 문제는 없다고 생각합니다. utf-16
은 바이너리 모드로 열어야 하므로 새로운 문제를 일으키지 않을 것입니다. utf-8
과의 상호 작용도 괜찮습니다. 값 0x0a
와 0x0d
는 멀티바이트 시퀀스의 일부로 발생할 수 없습니다.
유니버설 뉴라인 파일은 결국 일반 파일 readline
/readlines
메서드를 호출하므로 이터레이터(iterators) 및 xreadlines()
와 잘 작동할 것입니다.
유니버설 뉴라인은 임포트 시 자동으로 활성화되지만, open()
의 경우 명시적으로 open(..., "U")
라고 지정해야 합니다. 이는 논쟁의 여지가 있지만, 이 디자인에 대한 몇 가지 이유는 다음과 같습니다.
- 호환성 (Compatibility): 텍스트 파일에서
\r\n
을 자체적으로 해석하는 프로그램은 동작이 변경될 수 있습니다. 예를 들어, 다른 줄바꿈 규칙을 가진 파일을 열 때 경고하는 에디터가 있습니다. 유니버설 뉴라인이 기본값이 되면, 이러한 에디터는 저장 시 줄바꿈을 로컬 규칙으로 자동으로 변환할 것입니다. Unix에서 바이너리 파일을 텍스트 파일로 여는 프로그램도 동작이 변경될 수 있습니다. - 인터페이스 명확성 (Interface clarity): 유니버설 뉴라인은 입력 파일에만 지원되며, 입출력 파일에는 지원되지 않습니다. 이는 의미론이 모호해질 수 있기 때문입니다. 지금까지 읽은 모든 줄바꿈이 Mac 줄바꿈이었다면 Mac 줄바꿈으로 작성할 것인가요? 하지만 나중에 Unix 줄바꿈을 읽게 되면 어떻게 될까요?
newlines
속성은 텍스트 에디터와 같이 줄바꿈 규칙에 정말 관심 있는 프로그램이 파일에 어떤 규칙이 사용되었는지 확인할 수 있도록 포함됩니다. 그런 다음 동일한 줄바꿈 규칙으로 파일 (또는 복사본)을 저장할 수 있습니다 (또는 혼합된 줄바꿈이 있는 파일의 경우 사용자에게 무엇을 할지 묻거나 플랫폼 규칙으로 출력할 수 있습니다).
참고 구현의 한 항목에 대해 명시적으로 피드백이 요청됩니다. 유니버설 뉴라인 루틴이 전역 인터프리터 락(Global Interpreter Lock, GIL)을 획득해야 하는지 여부입니다. 현재는 그렇지 않지만, FileObject
의 필드를 수정할 수 있으므로 위험하다고 간주될 수 있습니다. 그러나 이러한 루틴은 fgets()
및 fread()
를 대체하는 것이기도 하므로 루틴이 호출될 때 락이 유지되는지 여부를 결정하기 어려울 수 있습니다. 더욱이, 유일한 위험은 두 스레드가 동시에 동일한 FileObject
를 읽을 경우 불필요한 줄바꿈이 보이거나 newlines
속성이 의도치 않게 혼합된 값으로 설정될 수 있다는 것입니다. 동시에 두 스레드에서 동일한 FileObject
를 읽는다면 어차피 문제가 발생할 수 있다고 주장할 수 있습니다.
fgets()
또는 fread()
대체 루틴에서는 전역적으로 접근 가능한 포인터가 조작되지 않고, 단순히 일부 정수 값 플래그만 조작되므로 코어 덤프(core dump) 발생 가능성은 0입니다.
유니버설 뉴라인 지원은 약간의 성능 저하가 있고, 모든 가능한 플랫폼에서 구현이 테스트되지 않았기 때문에 configure하는 동안 비활성화할 수 있습니다. 일부 플랫폼 (예: WinCE 또는 Palm 장치)에서는 어리석은 기능일 수도 있습니다. 유니버설 뉴라인 지원이 활성화되지 않으면 파일 객체는 newlines
속성을 가지지 않으므로, 현재 Python이 이 기능을 지원하는지 여부는 다음과 같이 간단하게 테스트할 수 있습니다.
if hasattr(open, 'newlines'):
print 'We have universal newline support'
이 테스트는 파일 유형 대신 open()
함수를 사용합니다. 이는 파일 유형을 사용할 수 없었던 Python 버전에서 실패하지 않도록 하기 위함입니다 (파일 유형은 유니버설 뉴라인 기능이 추가된 것과 동일한 릴리스에서 내장 네임스페이스에 추가되었습니다).
또한, 이 테스트는 Python 버전 2.5 이상에서는 open()
이 다시 함수가 되고 파일 유형과 동의어가 아니게 되면서 다시 실패한다는 점에 유의해야 합니다.
참고 구현 (Reference Implementation)
참고 구현은 SourceForge 패치 #476814에서 확인할 수 있습니다: https://bugs.python.org/issue476814
참조 (References)
없음.
저작권 (Copyright)
이 문서는 퍼블릭 도메인에 공개되었습니다.
⚠️ 알림: 이 문서는 AI를 활용하여 번역되었으며, 기술적 정확성을 보장하지 않습니다. 정확한 내용은 반드시 원문을 확인하시기 바랍니다.
Comments