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

Python 개선 제안 한국어 번역

PEP 278 – 범용 줄바꿈 지원

Author:
Jack Jansen <jack at cwi.nl>
Status:
Final
Type:
Standards Track
Created:
14-Jan-2002
Python-Version:
2.3
Post-History:


Table of Contents

번역·라이선스 안내

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

초록

이 PEP는 플랫폼 고유 형식이 아닌 줄바꿈 형식을 가진 파일에 대해 Python이 I/O를 지원하는 방법을 논의합니다. 이를 통해 각 플랫폼의 Python은 CR(Macintosh), LF(Unix), CR LF(Windows) 줄 끝을 가진 파일을 읽고 임포트할 수 있습니다.

현재 플랫폼의 표준과 맞지 않는 줄 끝을 가진 파일을 접하는 일이 점점 더 흔해지고 있습니다. 네트워크로 내려받은 파일, 다른 플랫폼의 파일 시스템을 원격으로 마운트한 경우, Mac과 Unix 줄 끝이라는 이중 표준을 가진 Mac OS X 등이 그 예입니다.

편집기나 컴파일러 같은 많은 도구가 이미 이를 매끄럽게 처리하고 있으므로, Python도 그렇게 한다면 좋을 것입니다.

명세

범용 줄바꿈 지원은 기본적으로 활성화되어 있지만, Python을 configure하는 과정에서 비활성화할 수 있습니다.

범용 줄바꿈 지원이 포함된 Python에서는 모든 import 문과 execfile() 호출에 대해 이 기능이 자동으로 활성화됩니다. eval()이나 exec에 대한 특별한 지원은 없습니다.

범용 줄바꿈 지원이 포함된 Python에서는 open()의 mode 매개변수에 “U”도 지정할 수 있으며, 이는 “범용 줄바꿈 해석을 적용하여 텍스트 파일을 입력용으로 연다”는 뜻입니다. “rb”와의 대칭을 위해 “rU” 모드도 허용됩니다. “U” 모드는 “+” 같은 다른 모드 플래그와 함께 사용할 수 없습니다. 입력 파일의 모든 줄 끝은 Python에서 '\n'으로 보이므로, 범용 줄바꿈을 처리하기 위해 다른 코드를 바꿀 필요가 거의 없습니다.

줄바꿈 변환은 데이터를 읽는 모든 호출에서 일어납니다: read(), readline(), readlines() 등.

다른 줄바꿈 규칙으로 파일에 출력하는 것은 특별히 지원하지 않으므로, mode “wU”도 허용되지 않습니다.

범용 줄바꿈 모드로 열린 파일 객체는 파일에서 사용된 줄바꿈 규칙을 반영하는 새 속성 “newlines”를 갖게 됩니다. 이 속성의 값은 None(아직 줄바꿈을 읽지 않음), "\r", "\n", "\r\n", 또는 지금까지 나타난 모든 줄바꿈 유형을 담은 튜플 중 하나입니다.

근거

범용 줄바꿈 지원은 Python이 아니라 C로 구현되어 있습니다. 이렇게 한 이유는 다른 줄바꿈 규칙을 가진 파일도 임포트할 수 있게 하여, Python Lib 디렉터리를 원격 파일 시스템 연결을 통해 공유하거나 Mac OS X에서 MacPython과 Unix-Python 사이에 공유할 수 있도록 하기 위함입니다. 이것이 실현 가능하려면 범용 줄바꿈 규칙이 성능에 미치는 영향이 충분히 작아야 하며, 이는 모든 임포트를 느리게 만들 Python 구현은 선택지가 될 수 없다는 뜻입니다. 또한 Visual C++와 다른 Windows 도구들이 아무렇지 않게 만들어 내는, 여러 줄바꿈 규칙이 섞인 파일 때문에, 파일에서 사용된 줄바꿈을 빠르게 검사하는 방식(플랫폼 고유의 줄바꿈이 보이면 임포트를 C 코드에 넘기는 방식)은 통하지 않습니다. 마지막으로, C 구현은 (Python 소스 모듈을 여는) 트레이스백 등도 쉽게 처리할 수 있게 해 줍니다.

범용 줄바꿈의 출력 구현은 없으며, Python 프로그램이 이를 스스로 처리하거나 그렇지 않으면 플랫폼 고유 규칙으로 파일을 작성할 것으로 예상합니다. 그 이유는 입력이 어려운 경우이고, 파일에 다른 줄바꿈을 출력하는 것은 Python에서 이미 충분히 쉽기 때문입니다.

또한 놀랍게도 출력 구현은 입력 구현보다 훨씬 어려울 것입니다. 많은 출력이 PyXXX_Print() 메서드를 통해 이루어지는데, 이 시점에서는 파일 객체를 더 이상 사용할 수 없고 FILE *만 남아 있기 때문입니다. 따라서 출력 구현은 어떻게든 FILE*에서 파일 객체로 거슬러 올라가야 하는데, 현재 줄바꿈 구분자가 저장된 곳이 바로 파일 객체이기 때문입니다.

입력 구현에는 이런 문제가 없습니다. Python 소스 트리에는 파일을 일부는 C에서, 일부는 Python에서 읽는 경우가 없으며, 확장 모듈에서도 그런 경우는 드물 것으로 예상됩니다. 이러한 경우가 존재한다면, 유일한 문제는 C에서 직접 수행되는 fread()나 fgets() 호출 중에는 파일 객체의 newlines(줄바꿈) 속성이 갱신되지 않는다는 점입니다.

fp.write()에 전달된 문자열만 fp.newlines를 줄 종결자로 사용하도록 변환되고 그 밖의 모든 출력은 변환되지 않는 부분적인 출력 구현은, 제가 보기에 지나치게 예상 밖의 동작입니다.

범용 줄바꿈에 대한 출력 지원이 없으므로 mode “rU+”도 지원하지 않습니다: 앞 단락에서 말한 의외성이 훨씬 더 강하게 나타날 것이기 때문입니다.

eval()이나 exec에 전달되는 문자열에서는 범용 줄바꿈을 지원하지 않습니다. 그런 문자열은 항상 표준 \n 줄바꿈 문자를 가진다고 상정하며, 문자열이 파일에서 온 것이라면 그 파일을 범용 줄바꿈으로 읽으면 됩니다.

유니코드와 관련해서는 특별한 문제가 없다고 생각합니다. utf-16 파일은 어차피 바이너리 모드로 열어야 하므로 새로운 문제를 일으키지 않을 것입니다. utf-8과의 상호 작용도 문제가 없습니다. 0x0a와 0x0d 값은 멀티바이트 시퀀스의 일부로 나타날 수 없기 때문입니다.

범용 줄바꿈 파일은 이터레이터 및 xreadlines()와도 잘 동작할 것입니다. 이들은 결국 일반 파일의 readline/readlines 메서드를 호출하기 때문입니다.

범용 줄바꿈은 임포트에서는 자동으로 활성화되지만 파일을 열 때는 그렇지 않으며, 이 경우 open(..., "U")라고 명시해야 합니다. 이 부분은 논의의 여지가 있지만, 이렇게 설계한 몇 가지 이유는 다음과 같습니다.

  • 호환성. 텍스트 파일의 \r\n을 이미 자체적으로 해석하는 프로그램이 동작하지 않게 됩니다. 그런 프로그램의 예로는 다른 줄바꿈 규칙을 가진 파일을 열 때 경고를 표시하는 편집기를 들 수 있습니다. 범용 줄바꿈이 기본값이 된다면, 그런 편집기는 저장할 때 줄 끝을 아무 말 없이 로컬 규칙으로 바꿔 버릴 것입니다. Unix에서 바이너리 파일을 텍스트 파일로 여는 프로그램도 동작하지 않게 됩니다(다만 그런 프로그램은 그래도 싸다고 주장할 수도 있습니다 :-).
  • 인터페이스의 명확성. 범용 줄바꿈은 입력 파일에만 지원되고 입출력 파일에는 지원되지 않습니다. 의미가 모호해지기 때문입니다. 지금까지 읽은 내용이 모두 Mac 줄바꿈이었다면 Mac 줄바꿈으로 써야 하겠습니까? 그런데 그 뒤에 Unix 줄바꿈을 읽게 된다면 어떻게 하겠습니까?

newlines 속성은 텍스트 편집기처럼 줄바꿈 규칙을 실제로 신경 쓰는 프로그램이 파일에 무엇이 들어 있었는지 확인할 수 있도록 포함되었습니다. 그러면 이런 프로그램은 같은 줄바꿈 규칙으로 파일(또는 그 사본)을 저장할 수 있습니다(줄바꿈이 섞인 파일이라면 사용자에게 어떻게 할지 묻거나 플랫폼 규칙으로 출력할 수 있습니다).

참조 구현의 한 가지 항목에 대해 명시적으로 의견을 구합니다: 범용 줄바꿈 루틴이 전역 인터프리터 잠금을 획득해야 하는지 여부입니다. 현재는 획득하지 않지만, 이 루틴들이 FileObject의 필드를 수정할 수 있으므로 위험을 무릅쓰는 것으로 볼 수도 있습니다. 하지만 이 루틴들은 fgets()와 fread()를 대체하기도 하므로, 루틴이 호출될 때 잠금이 유지되고 있는지 여부를 판단하기 어려울 수 있습니다. 게다가 유일한 위험은 두 스레드가 같은 FileObject를 동시에 읽을 경우 불필요한 줄바꿈이 보이거나 newlines 속성이 의도치 않게 mixed로 설정될 수 있다는 것뿐입니다. 두 스레드에서 같은 FileObject를 동시에 읽는다면 어차피 문제를 자초하는 것이라고 주장하고 싶습니다.

fgets()나 fread() 대체 루틴에서는 전역적으로 접근 가능한 포인터를 전혀 조작하지 않고 정수 값 플래그 몇 개만 다루므로, 코어 덤프가 발생할 가능성은 전혀 없다는 점에 유의하십시오(라고 그는 말했습니다 :-).

범용 줄바꿈 지원은 약간의 성능 저하가 있고, 게다가 그 구현이 아직 생각할 수 있는 모든 플랫폼에서 테스트되지는 않았기 때문에 configure 단계에서 비활성화할 수 있습니다. 또한 일부 플랫폼(예를 들어 WinCE나 Palm 기기)에서는 무의미할 수도 있습니다. 범용 줄바꿈 지원이 활성화되지 않으면 파일 객체에 newlines 속성이 없으므로, 현재 Python에 이 속성이 있는지는 다음과 같이 간단히 테스트할 수 있습니다:

if hasattr(open, 'newlines'):
   print 'We have universal newline support'

이 테스트는 file 타입이 없던 Python 버전에서도 실패하지 않도록 file 타입 대신 open() 함수를 사용한다는 점에 유의하십시오(file 타입은 범용 줄바꿈 기능이 추가된 것과 같은 릴리스에서 내장 네임스페이스에 추가되었습니다).

또한 open()이 다시 함수가 되어 더 이상 file 타입과 동의어가 아니게 된 Python 버전 = 2.5에서는 이 테스트가 다시 실패한다는 점에도 유의하십시오.

참조 구현

참조 구현은 SourceForge 패치 #476814에서 확인할 수 있습니다: https://bugs.python.org/issue476814

참고 문헌

없음.