2to3 - 파이썬 2에서 파이썬 3으로 자동 코드 변환
***********************************************

2to3는 파이썬 2.x 소스 코드를 유효한 파이썬 3.x 코드로 변환하기 위해
일련의 *변환자(fixers)*를 적용하는 프로그램입니다. 표준 라이브러리는
많은 양의 변환자를 제공하고 있어 코드 대부분을 처리할 수 있을 것입니다
. 2to3에서 사용하는 모듈인 "lib2to3" 는 유연하고 제네릭합니다. 따라서
2to3 프로그램을 위해 당신만의 변환자를 작성할 수 있습니다. 또한
"lib2to3" 는 파이썬 코드를 자동으로 수정해주는 커스텀 응용 프로그램에
서도 사용할 수 있습니다.


2to3 사용법
===========

파이썬 인터프리터가 설치될 때, 보통 2to3 스크립트도 같이 설치됩니다.
2to3 스크립트 파일은 파이썬 루트 디렉터리의 하위 디렉터리인
"Tools/scripts" 에서 찾을 수 있습니다.

2to3의 기본 인자는 변환하고자 하는 파일이나 디렉터리 리스트입니다. 디
렉터리의 경우 하위 폴더의 파이썬 소스까지 적용됩니다.

샘플 파이썬 2.x 코드가 여기 있습니다. "example.py":

   def greet(name):
       print "Hello, {0}!".format(name)
   print "What's your name?"
   name = raw_input()
   greet(name)

명령줄에서 2to3를 실행하면 이 코드를 파이썬 3.x 코드로 바꿀 수 있습니
다:

   $ 2to3 example.py

원본 파일과 변환 결과를 비교한 차이점(diff)이 출력됩니다. 2to3은 원본
소스 파일에 필요한 수정사항을 바로 적용할 수도 있습니다. ("-n" 옵션이
적용되지 않았다면 원본 파일에 대한 백업이 생성될 것입니다.) "-w" 옵션
을 사용하면 바로 원본 파일이 수정됩니다.

   $ 2to3 -w example.py

"example.py" 를 변환한 결과는 다음과 같습니다.

   def greet(name):
       print("Hello, {0}!".format(name))
   print("What's your name?")
   name = input()
   greet(name)

변환 과정에서 들여쓰기와 주석은 그대로 보존됩니다.

기본적으로 2to3는 미리 정의된 변환자 를 사용하여 실행됩니다. "-l" 옵션
을 사용하면 사용 가능한 모든 변환자를 볼 수 있습니다. 특정 변환자만 명
시적으로 설정하고 싶으시면 "-f" 를 사용하시면 됩니다. 마찬가지로 "-x"
옵션으로 특정 변환자를 비활성화할 수도 있습니다. 다음 예는 "imports"
와 "has_key" 변환자만 사용한 것입니다.

   $ 2to3 -f imports -f has_key example.py

다음은 "apply" 변환자만 빼고 모든 변환자를 실행하는 명령어입니다.

   $ 2to3 -x apply example.py

몇몇 변환자는 기본적으로 실행되지 않기 때문에 명시적으로 명령줄에서 설
정해야 합니다. 기본 변환자에 "idioms" 변환자를 추가한 예시가 여기 있습
니다.

   $ 2to3 -f all -f idioms example.py

모든 기본 변환자를 활성화하기 위해 "all" 값을 사용한 것을 주목해주세요
.

때때로 2to3는 자동 변환을 하지 못하고 당신의 코드에서 수정이 필요한 부
분을 찾을 수도 있습니다. 이러면 파일의 비교 결과 아래에 경고 문구를 출
력할 것입니다. 당신은 이 소스코드를 3.x 버전에 맞도록 경고 사항을 수정
해야 합니다.

2to3는 doctest도 수정할 수 있습니다. 이것을 활성화하기 위해서는 "-d"
옵션을 사용하세요. 이것은 *오직* doctest만 수정한다는 것을 명심하세요.
이것을 사용하기 위해서 꼭 적합한 파이썬 모듈이 필요한 것은 아닙니다.
예를 들어 reST 문서에 있는 예와 같은 doctest도 이 옵션과 함께 수정할
수 있습니다.

"-v" 옵션은 변환 과정 동안 더 자세한 정보를 출력하게 해줍니다.

어떤 print 문장의 경우는 문장 또는 함수 호출로 파싱될 수 있기 때문에
2to3이 print 함수를 포함한 파일을 항상 처리할 수 있는 것은 아닙니다.
2to3이 "from __future__ import print_function" 이란 컴파일러 지시어를
찾았다면 2to3는 "print()" 를 함수로 처리하도록 내부 처리 문법을 변경할
것입니다. 이러한 변경은 "-p" 옵션을 가지고 직접 활성화할 수도 있습니다
. 출력 문장이 이미 변경된 코드에 변환자를 실행하기 위해 "-p" 옵션을 사
용하세요.

"-o" 또는 "--output-dir" 옵션을 사용하면 출력 파일이 쓰일 디렉터리를
설정할 수 있습니다.:option:*!-n* 옵션은 입력 파일을 덮어쓰지 않아 백업
파일이 필요 없을 때 사용할 수 있습니다.

버전 3.2.3에 추가: "-o" 옵션이 추가되었습니다.

"-W" 또는 "--write-unchanged-files" 옵션은 변경 사항이 없더라도 항상
출력 파일을 쓰도록 합니다. 이것을 "-o" 옵션과 함께 쓰면 한 디렉터리에
있는 전체 파이썬 소스 트리를 파이썬 3.x로 변환해서 다른 디렉터리로 복
사할 때 유용하게 사용할 수 있습니다. 이치에 맞게 하기 위해 이 옵션은
"-w" 옵션을 포함하고 있습니다.

버전 3.2.3에 추가: "-W" 옵션이 추가되었습니다.

"--add-suffix" 옵션은 모든 출력 파일 이름 뒤에 추가할 문자열을 지정합
니다. 다른 파일 이름으로 저장할 때 백업 파일이 필요하지 않다면 "-n" 옵
션을 같이 사용해야 합니다. 예시:

   $ 2to3 -n -W --add-suffix=3 example.py

이 명령어는 출력 파일의 이름을 "example.py3" 로 만들어 줍니다.

버전 3.2.3에 추가: "--add-suffix" 옵션이 추가되었습니다.

한 디렉터리에서 다른 디렉터리로 전체 프로젝트를 변환하고 싶을 때는 다
음과 같이 하면 됩니다.

   $ 2to3 --output-dir=python3-version/mycode -W -n python2-version/mycode


변환자 목록
===========

변환되는 코드의 각각 단계는 변환자 안에 캡슐화되어 있습니다. "2to3 -l"
명령어를 실행하면 변환자 목록을 보실 수 있습니다. 위에 적어놓은 것 과
같이, 각 변환자는 개별적으로 활성화/비활성화를 할 수 있습니다. 변환자
들에 대한 자세한 설명이 아래에 있습니다.

apply

   "apply()" 사용을 제거합니다. 예를 들어 "apply(function, *args,
   **kwargs)" 를 "function(*args, **kwargs)" 로 변경합니다.

asserts

   폐지된 "unittest" 메서드 이름을 올바른 것으로 변경합니다.

   +----------------------------------+--------------------------------------------+
   | 변경 전                          | 변경 후                                    |
   |==================================|============================================|
   | "failUnlessEqual(a, b)"          | "assertEqual(a, b)"                        |
   +----------------------------------+--------------------------------------------+
   | "assertEquals(a, b)"             | "assertEqual(a, b)"                        |
   +----------------------------------+--------------------------------------------+
   | "failIfEqual(a, b)"              | "assertNotEqual(a, b)"                     |
   +----------------------------------+--------------------------------------------+
   | "assertNotEquals(a, b)"          | "assertNotEqual(a, b)"                     |
   +----------------------------------+--------------------------------------------+
   | "failUnless(a)"                  | "assertTrue(a)"                            |
   +----------------------------------+--------------------------------------------+
   | "assert_(a)"                     | "assertTrue(a)"                            |
   +----------------------------------+--------------------------------------------+
   | "failIf(a)"                      | "assertFalse(a)"                           |
   +----------------------------------+--------------------------------------------+
   | "failUnlessRaises(exc, cal)"     | "assertRaises(exc, cal)"                   |
   +----------------------------------+--------------------------------------------+
   | "failUnlessAlmostEqual(a, b)"    | "assertAlmostEqual(a, b)"                  |
   +----------------------------------+--------------------------------------------+
   | "assertAlmostEquals(a, b)"       | "assertAlmostEqual(a, b)"                  |
   +----------------------------------+--------------------------------------------+
   | "failIfAlmostEqual(a, b)"        | "assertNotAlmostEqual(a, b)"               |
   +----------------------------------+--------------------------------------------+
   | "assertNotAlmostEquals(a, b)"    | "assertNotAlmostEqual(a, b)"               |
   +----------------------------------+--------------------------------------------+

basestring

   "basestring" 을 "str" 로 변환합니다.

buffer

   "buffer" 를 "memoryview" 로 변환합니다. "memoryview" API가 "buffer"
   API와 비슷하긴 하지만 완전히 같진 않아서 이 변환자는 선택적으로 실
   행됩니다.

dict

   딕셔너리 이터레이션 메서드를 변환합니다. "dict.iteritems()" 를
   "dict.items()" 로, "dict.iterkeys()" 를 "dict.keys()" 로,
   "dict.itervalues()" 를 "dict.values()" 로 변경합니다. 마찬가지로
   "dict.viewitems()", "dict.viewkeys()", "dict.viewvalues()" 를 각각
   "dict.items()", "dict.keys()", "dict.values()" 로 변경합니다. 기존
   의 "dict.items()", "dict.keys()", "dict.values()" 의 사용을 "list"
   로 감싸도록 바꿉니다.

except

   "except X, T" 를 "except X as T" 로 변환합니다.

exec

   "exec" 문장을 "exec()" 함수로 변환합니다.

execfile

   "execfile()" 사용을 제거합니다. "execfile()" 에 사용되는 인자는
   "open()", "compile()", "exec()" 을 사용하도록 바뀝니다.

exitfunc

   "sys.exitfunc" 대입이 "atexit" 모듈을 사용하도록 바뀝니다.

filter

   "filter()" 함수 사용을 "list" 로 감싸도록 바꿉니다.

funcattrs

   이름이 변경된 함수 어트리뷰트를 변환합니다. 예를 들어
   "my_function.func_closure" 를 "my_function.__closure__" 로 변경합니
   다.

future

   "from __future__ import new_feature" 구문을 제거합니다.

getcwdu

   "os.getcwdu()" 를 "os.getcwd()" 로 변경합니다.

has_key

   "dict.has_key(key)" 를 "key in dict" 로 바꿉니다.

idioms

   이 선택적인 변환자는 이디엄을 더 사용하도록 파이썬 코드를 변환해줍
   니다. "type(x) is SomeClass" 나 "type(x) == SomeClass" 같은 형 비교
   는 "isinstance(x, SomeClass)" 로 변환합니다. "while 1" 는 "while
   True" 로 변환합니다. 또한 이 변환자는 "sorted()" 가 올바른 위치에
   사용될 수 있도록 수정합니다. 예를 들어 다음 코드는

      L = list(some_iterable)
      L.sort()

   아래와 같이 변경됩니다.

      L = sorted(some_iterable)

import

   같은 단계 경로의 임포트를 찾아 상대 경로 임포트로 변경합니다.

imports

   표준 라이브러리에 있는 모듈의 이름 변경 사항을 처리합니다.

imports2

   표준 라이브러리에 있는 또 다른 모듈의 이름 변경 사항을 처리합니다.
   기술적인 제한 사항 때문에 "imports" 변환자와 분리했습니다.

input

   "input(prompt)" 를 "eval(input(prompt))" 로 변경합니다.

intern

   "intern()" 를 "sys.intern()" 로 변경합니다.

isinstance

   "isinstance()" 의 두 번째 인자에서 중복된 형을 수정합니다. 예를 들
   어 "isinstance(x, (int, int))" 를 "isinstance(x, int)" 로,
   "isinstance(x, (int, float, int))" 를 "isinstance(x, (int, float))"
   로 변경합니다.

itertools_imports

   "itertools.ifilter()",  "itertools.izip()", "itertools.imap()" 임포
   트를 제거합니다. "itertools.ifilterfalse()" 임포트를
   "itertools.filterfalse()" 로 바꿉니다.

itertools

   "itertools.ifilter()", "itertools.izip()", "itertools.imap()" 를 각
   각 그것에 맞는 내장 함수로 변경합니다. "itertools.ifilterfalse()"
   를 "itertools.filterfalse()" 로 변경합니다.

long

   "long" 을 "int" 로 바꿉니다.

map

   "map()" 을 "list" 로 감싸도록 바꿉니다. "map(None, x)" 를 "list(x)"
   로 바꿉니다. "from future_builtins import map" 를 사용하면 이 변환
   자가 비활성화됩니다.

metaclass

   구식의 메타 클래스 문법(클래스 바디에 "__metaclass__ = Meta" 를 사
   용)을 새로운 문법("class X(metaclass=Meta)")으로 변경합니다.

methodattrs

   구식의 메서드 어트리뷰트 이름을 수정합니다. 예를 들어
   "meth.im_func" 를 "meth.__func__" 로 변경합니다.

ne

   구식의 부등호 문법인 "<>" 을 "!=" 로 변경합니다.

next

   이터레이터의 "next()" 메서드 사용을 "next()" 함수로 변경합니다. 또
   한 "next()" 메서드를 "__next__()" 로 바꿉니다.

nonzero

   "__nonzero__()" 를 "__bool__()" 로 변경합니다.

numliterals

   8진수 리터럴을 새 문법으로 변경합니다.

operator

   "operator" 모듈에 있는 다양한 함수 호출을 그것에 대응하는 다른 함수
   호출로 변경합니다. "import collections.abc" 와 같이 필요하다면
   "import" 구문도 추가됩니다. 다음과 같이 변경합니다.

   +------------------------------------+-----------------------------------------------+
   | 변경 전                            | 변경 후                                       |
   |====================================|===============================================|
   | "operator.isCallable(obj)"         | "callable(obj)"                               |
   +------------------------------------+-----------------------------------------------+
   | "operator.sequenceIncludes(obj)"   | "operator.contains(obj)"                      |
   +------------------------------------+-----------------------------------------------+
   | "operator.isSequenceType(obj)"     | "isinstance(obj, collections.abc.Sequence)"   |
   +------------------------------------+-----------------------------------------------+
   | "operator.isMappingType(obj)"      | "isinstance(obj, collections.abc.Mapping)"    |
   +------------------------------------+-----------------------------------------------+
   | "operator.isNumberType(obj)"       | "isinstance(obj, numbers.Number)"             |
   +------------------------------------+-----------------------------------------------+
   | "operator.repeat(obj, n)"          | "operator.mul(obj, n)"                        |
   +------------------------------------+-----------------------------------------------+
   | "operator.irepeat(obj, n)"         | "operator.imul(obj, n)"                       |
   +------------------------------------+-----------------------------------------------+

paren

   리스트 컴프리헨션 안에 괄호가 필요한 경우 추가합니다. 예를 들어 "[x
   for x in 1, 2]" 를 "[x for x in (1, 2)]" 로 변경합니다.

print

   "print" 구문을 "print()" 함수로 변경합니다.

raise

   "raise E, V" 를 "raise E(V)" 로, "raise E, V, T" 를 "raise
   E(V).with_traceback(T)" 로 변경합니다. 만약 "E" 가 튜플인 경우, 변
   환된 결과물은 동작하지 않을 것입니다. 왜냐하면 튜플이 예외를 대체하
   는 것은 3.0부터 사라졌기 때문입니다.

raw_input

   "raw_input()" 를 "input()" 로 변경합니다.

reduce

   "reduce()" 를 "functools.reduce()" 로 변경합니다.

reload

   "reload()" 를 "importlib.reload()" 로 변경합니다.

renames

   "sys.maxint" 를 "sys.maxsize" 로 변경합니다.

repr

   백틱 repr을 "repr()" 함수로 바꿉니다.

set_literal

   "set" 생성자를 집합 리터럴로 바꿉니다. 이 변환자는 선택적입니다.

standarderror

   "StandardError" 를 "Exception" 로 바꿉니다.

sys_exc

   더 사용되지 않을 "sys.exc_value", "sys.exc_type",
   "sys.exc_traceback" 를 "sys.exc_info()" 로 변경합니다.

throw

   제너레이터 "throw()" 메서드의 API 변경 사항을 반영합니다.

tuple_params

   묵시적으로 튜플 매개 변수를 언패킹하는 것을 제거합니다. 이로 인해
   이 변환자는 임시 변수를 추가합니다.

types

   "types" 모듈에서 몇몇 멤버가 삭제되어 코드가 동작하지 않던 것을 수
   정합니다.

unicode

   "unicode" 를 "str" 로 변경합니다.

urllib

   "urllib" 와 "urllib2" 를 "urllib" 패키지로 변경합니다.

ws_comma

   쉼표로 구분뒨 아이템 목록에서 필요 이상의 공백을 제거합니다. 이 변
   경자는 선택적입니다.

xrange

   "xrange()" 를 "range()" 로 바꿉니다. 기존 "range()" 를 "list" 로 감
   쌉니다.

xreadlines

   "for x in file.xreadlines()" 를 "for x in file" 로 변경합니다.

zip

   "zip()" 를 "list" 로 감쌉니다. 이 변환자는 "from future_builtins
   import zip" 가 있을 때는 비활성화됩니다.


"lib2to3" - 2to3 라이브러리
===========================

**소스 코드:** Lib/lib2to3/

======================================================================

참고:

  "lib2to3" API는 미래에 크게 바뀔 수 있기 때문에 안정적이지 않다고 생
  각해야 합니다.
