Содержание страницы
25.4. 2to3 – автоматическое преобразование кода Python 2 в 3¶2to3 - Automated Python 2 to 3 code translation
2to3 – это программа на Python, которая читает исходный код Python 2.x и применяет ряд преобразователей для преобразования его в корректный код Python 3.x. Стандартная библиотека содержит обширный набор преобразователей, которые справляются почти с любым кодом. Однако библиотека поддержки 2to3 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 также может рефакторить доктесты. Чтобы включить этот режим, используйте флаг -d. Обратите внимание, что только доктесты будут подвергнуты рефакторингу. При этом не требуется, чтобы модуль был корректным Python. Например, примеры в стиле доктестов в документе reST также можно рефакторить с помощью этой опции.
Опция -v включает вывод дополнительной информации о процессе преобразования.
Поскольку некоторые операторы print можно разобрать как вызовы функций или как инструкции, 2to3 не всегда может читать файлы, содержащие функцию print. Когда 2to3 обнаруживает указание компилятора from __future__ import print_function, он изменяет свою внутреннюю грамматику, чтобы интерпретировать print() как функцию. Это изменение также можно включить вручную с помощью флага -p. Используйте -p для запуска фиксеров на коде, в котором операторы print уже преобразованы.
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 при необходимости.
- 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¶
- Преобразует восьмеричные литералы в новый синтаксис.
- 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.
25.4.3. lib2to3 – библиотека 2to3¶lib2to3 - 2to3’s library
Примечание
API lib2to3 следует считать нестабильным и в будущем оно может кардинально измениться.