Содержание страницы
25.4. 2to3 – автоматическое преобразование кода Python 2 в 3¶2to3 - Automated Python 2 to 3 code translation
2to3 – это программа на Python, которая читает исходный код Python 2.x и применяет ряд фиксеров, чтобы преобразовать его в корректный код Python 3.x. Стандартная библиотека содержит богатый набор фиксеров, которые обрабатывают почти любой код. Однако вспомогательная библиотека lib2to3 является гибкой и универсальной, поэтому можно написать собственные фиксеры для 2to3. lib2to3 также можно адаптировать для пользовательских приложений, где требуется автоматическое редактирование кода Python.
25.4.1. Использование 2to3¶Using 2to3
2to3 обычно устанавливается вместе с интерпретатором Python как скрипт. Он также находится в каталоге Tools/scripts корневого каталога Python.
Основные аргументы 2to3 – это список файлов или каталогов для преобразования. Каталоги обходятся рекурсивно в поисках исходников Python.
Вот пример исходного файла Python 2.x, example.py:
def greet(name):
print "Hello, {0}!".format(name)
print "What's your name?"
name = raw_input()
greet(name)
Его можно преобразовать в код Python 3.x с помощью 2to3 в командной строке:
$ 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 находит в исходном коде место, которое нужно изменить, но не может исправить автоматически. В этом случае 2to3 выводит предупреждение под diff для файла. Следует обработать это предупреждение, чтобы получить корректный код 3.x.
2to3 также может рефакторить doctest'ы. Для включения этого режима используйте флаг -d. Обратите внимание, что только doctest'ы будут подвергнуты рефакторингу. При этом модуль не обязан быть корректным Python. Например, примеры в стиле doctest в reST-документе также можно рефакторить с помощью этой опции.
Опция -v включает вывод дополнительной информации о процессе перевода.
Поскольку некоторые операторы print можно разобрать как вызовы функций или как инструкции, 2to3 не всегда может читать файлы, содержащие функцию print. Когда 2to3 обнаруживает указание компилятора from __future__ import print_function, он изменяет свою внутреннюю грамматику, чтобы интерпретировать print() как функцию. Это изменение также можно включить вручную с помощью флага -p. Используйте -p для запуска фиксеров на коде, в котором операторы print уже преобразованы.
Опция -o или --output-dir позволяет указать альтернативный каталог для записи обработанных выходных файлов. Флаг -n обязателен при использовании этой опции, так как резервные копии не имеют смысла, если исходные файлы не перезаписываются.
Новое в версии 3.2.3: Добавлена опция -o.
Флаг -W или --write-unchanged-files указывает 2to3 всегда записывать выходные файлы, даже если в файл не требовалось вносить изменения. Это наиболее полезно в сочетании с -o, чтобы скопировать всё дерево исходного кода Python с переводом из одного каталога в другой. Эта опция подразумевает флаг -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
25.4.2. Фиксеры¶Fixers
Каждый шаг преобразования кода инкапсулирован в фиксере. Команда 2to3 -l выводит их список. Как уже описано выше, каждый можно включить или отключить по отдельности. Ниже они описаны подробнее.
- apply¶
Удаляет использование apply(). Например, apply(function, *args, **kwargs) преобразуется в function(*args, **kwargs).
- buffer¶
Преобразует buffer в memoryview. Этот фиксер необязателен, поскольку API memoryview похож, но не полностью совпадает с API buffer.
- callable¶
Преобразует callable(x) в isinstance(x, collections.Callable), добавляя импорт collections при необходимости. Обратите внимание, что callable(x) была возвращена в Python 3.2, поэтому если не планируется поддержка Python 3.1, этот фиксер можно отключить.
- 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.
- execfile¶
Удаляет использование execfile(). Аргумент execfile() оборачивается вызовами open(), compile() и exec().
- 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¶
Этот дополнительный фиксер выполняет несколько преобразований, делающих код Python более идиоматичным. Сравнения типов, такие как 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)).
- itertools_imports¶
Удаляет импорты itertools.ifilter(), itertools.izip() и itertools.imap(). Импорты itertools.ifilterfalse() также заменяются на itertools.filterfalse().
- itertools¶
Заменяет использование itertools.ifilter(), itertools.izip() и itertools.imap() на их встроенные эквиваленты. itertools.ifilterfalse() заменяется на itertools.filterfalse().
- 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¶
Преобразует восьмеричные литералы в новый синтаксис.
- operator¶
Преобразует вызовы различных функций из модуля operator в другие, но эквивалентные вызовы функций. При необходимости добавляются соответствующие операторы import, например import collections. Выполняются следующие преобразования:
Из В operator.isCallable(obj) hasattr(obj, '__call__') operator.sequenceIncludes(obj) operator.contains(obj) operator.isSequenceType(obj) isinstance(obj, collections.Sequence) operator.isMappingType(obj) isinstance(obj, collections.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)].
- raise¶
Преобразует raise E, V в raise E(V), а raise E, V, T в raise E(V).with_traceback(T). Если E – кортеж, преобразование будет некорректным, так как подстановка кортежей вместо исключений была удалена в версии 3.0.
- reduce¶
Обрабатывает перенос reduce() в functools.reduce().
- renames¶
Изменяет sys.maxint на sys.maxsize.
- set_literal¶
Заменяет использование конструктора set на литералы множеств. Этот фиксер является необязательным.
- sys_exc¶
Изменяет устаревшие sys.exc_value, sys.exc_type, sys.exc_traceback на использование sys.exc_info().
- throw¶
Исправляет изменение API в методе throw() генератора.
- tuple_params¶
Удаляет неявную распаковку параметров кортежа. Этот фиксер вставляет временные переменные.
- urllib¶
Обрабатывает переименование urllib и urllib2 в urllib пакет.
- ws_comma¶
Удаляет лишние пробелы из элементов, разделённых запятыми. Этот фиксер необязателен.
- xreadlines¶
Изменяет for x in file.xreadlines() на for x in file.