2to3 — Автоматизированная трансляция кода Python 2 в 3

2to3 - это программа на языке Python, которая читает исходный код Python 2.x и применяет ряд исправителей для преобразования его в правильный код Python 3.x. Стандартная библиотека содержит богатый набор корректоров, которые справятся почти со всем кодом. Однако библиотека поддержки 2to3 lib2to3 является гибкой и универсальной библиотекой, поэтому для 2to3 можно написать свои собственные фиксаторы.

Использование 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

Выводится сравнение с исходным файлом. 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 запускает набор predefined fixers. Флаг -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 не может исправить его автоматически. В этом случае 2to3 выведет предупреждение под diff для файла. Вы должны устранить предупреждение, чтобы получить совместимый код версии 3.x.

2to3 также может рефакторить доктесты. Чтобы включить этот режим, используйте флаг -d. Обратите внимание, что рефакторингу будут подвергаться только доктесты. Это также не требует, чтобы модуль был действительным Python. Например, доктесты, подобные примерам в документе reST, также могут быть отрефакторены с помощью этой опции.

Опция -v позволяет выводить дополнительную информацию о процессе перевода.

Поскольку некоторые операторы печати могут быть разобраны как вызовы функций или операторы, 2to3 не всегда может читать файлы, содержащие функцию печати. Когда 2to3 обнаруживает наличие директивы компилятора from __future__ import print_function, он изменяет свою внутреннюю грамматику, чтобы интерпретировать print() как функцию. Это изменение можно также включить вручную с помощью флага -p. Используйте -p для запуска исправлений в коде, в котором уже были преобразованы операторы печати. Также -e можно использовать для превращения exec() в функцию.

Опция -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

Фиксаторы

Каждый шаг преобразования кода заключен в фиксатор. Команда 2to3 -l перечисляет их. Как и documented above, каждый из них можно включать и выключать по отдельности. Более подробно они описаны здесь.

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. Этот корректор необязателен, поскольку API memoryview похож, но не полностью совпадает с API buffer.

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

Этот дополнительный корректор выполняет несколько преобразований, которые делают код 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), а 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

Преобразует восьмеричные литералы в новый синтаксис.

operator

Преобразует вызовы различных функций в модуле operator в другие, но эквивалентные вызовы функций. При необходимости добавляются соответствующие утверждения import, например import collections.abc. Выполняется следующее отображение:

С сайта

На

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

Заменяет функцию backtick repr на функцию repr().

set_literal

Заменяет использование конструктора set на литералы множеств. Это исправление необязательно.

standarderror

Переименовывает StandardError в Exception.

sys_exc

Изменяет устаревшие sys.exc_value, sys.exc_type, sys.exc_traceback на использование sys.exc_info().

throw

Исправляет изменение API в методе генератора throw().

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/.


Deprecated since version 3.11, will be removed in version 3.13: Python 3.9 перешел на синтаксический анализатор PEG (см. PEP 617), а lib2to3 использует менее гибкий синтаксический анализатор LL(1). Python 3.10 включает новый синтаксис языка, который не разбирается LL(1) синтаксическим анализатором lib2to3 (см. PEP 634). Модуль lib2to3 был помечен как ожидающий устаревания в Python 3.9 (выдавая PendingDeprecationWarning при импорте) и полностью устарел в Python 3.11 (выдавая DeprecationWarning). Он будет удален из стандартной библиотеки в Python 3.13. Рассмотрите альтернативы сторонних разработчиков, такие как LibCST или parso.

Примечание

API lib2to3 следует считать нестабильным и в будущем он может сильно измениться.

Вернуться на верх