# 2to3 — Traducción automática de código de Python 2 a 3

2to3 es un programa de Python que lee el código fuente de Python 2.x y aplica una serie de fixers para transformarlo en un código válido de Python 3.x. La biblioteca estándar contiene un amplio conjunto de arreglos que manejarán casi todo el código. Biblioteca de soporte 2to3 `lib2to3` es, sin embargo, una biblioteca flexible y genérica, por lo que es posible escribir sus propios arreglos para 2to3.

Obsoleto desde la versión 3.11, se eliminará en la versión 3.13: El módulo `lib2to3` se marcó como obsoleto en Python 3.9 (lanzando `PendingDeprecationWarning` cuando sea importado) y totalmente obsoleto en Python 3.11 (lanzando `DeprecationWarning`). La herramienta `2to3` es parte de eso. Se eliminará en Python 3.13.

## Usando 2to3

2to3 generalmente estará instalada con el interprete de Python como un script. También se encuentra ubicada en el directorio `Tools/scripts` en la raíz de Python.

Los argumentos básicos de 2to3 son una lista de archivos o directorios a convertir. Los directorios se recorren recursivamente en búsqueda de archivos en Python.

Este es un ejemplo de un archivo en Python 2.x, `example.py`:

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

Puede ser convertido a Python 3.x vía 2to3 desde la línea de comandos:

    $ 2to3 example.py

Se imprime un diff del archivo fuente original. 2to3 también puede escribir las modificaciones necesarias directamente en el archivo fuente. (Se hace una copia de respaldo del archivo original a menos que se proporcione `-n`.) La escritura de los cambios se habilita con la opción `-w`:

    $ 2to3 -w example.py

Después de la conversión, `example.py` se ve de la siguiente manera:

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

Los comentarios y la identación exacta se conservan durante todo el proceso de conversión.

Por defecto, 2to3 corre un conjunto de fixers predefinidos. La opción `-l` lista todos los fixers posibles. Se puede pasar un conjunto explícito de fixers con la opción `-x`. Asimismo la opción `-x` deshabilita el fixer que se explicita. El siguiente ejemplo corre solo solo los fixers `imports` y `has_key`:

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

Este comando corre todos los fixers excepto el `apply` fixer:

    $ 2to3 -x apply example.py

Algunos fixers son explícitos, esto quiere decir que no corren por defecto y deben ser listados en la línea de comando para que se ejecuten. Acá, además de los fixers por defectos, se ejecuta el fixer `idioms`:

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

Puede observarse que pasar `all` habilita todos los fixers por defecto.

Algunas veces 2to3 va a encontrar algo en su código que necesita ser modificado, pero 2to3 no puede hacerlo automáticamente. En estos casos, 2to3 va a imprimir una advertencia debajo del diff del archivo. Deberá tomar nota de la advertencia para obtener un código compatible con 3.x.

2to3 también puede refactorizar doctest. Para habilitar este modo, use la opción `-d`. Tenga en cuenta que solo los doctest serán refactorizados. Esto tampoco requiere que el módulo sea válido en Python. Por ejemplo, doctest de ejemplo en un documento reST también pueden ser refactorizados con esta opción.

La opción `-v` habilita la salida de más información en el proceso de conversión.

Dado que algunas declaraciones de impresión se pueden analizar como llamadas a funciones o declaraciones, 2to3 no siempre puede leer archivos que contienen la función de impresión. Cuando 2to3 detecta la presencia de la directiva del compilador `from __future__ import print_function`, modifica su gramática interna para interpretar `print()` como una función. Este cambio también se puede habilitar manualmente con la opción `-p`. Utilice `-p` para ejecutar correctores en el código que ya tiene sus declaraciones de impresión convertidas. También `-e` puede usarse para hacer `exec()` una función.

La opción `-o` o la opción `--output-dir` permiten designar un directorio alternativo para que se guarden los archivos procesados. La opción `-n` es necesaria ya que los archivos de respaldo no tienen sentido cuando no se sobreescriben los archivos originales.

Nuevo en la versión 3.2.3: Se agregó la opción :option:` !-o`.

La opción `-W` o `--write-unchanged-files` le dice a 2to3 que siempre escriba archivos de salida, incluso si no se requieren hacer cambios en el archivo. Esto es muy útil con la opción `-o` para que copie el árbol completo de código Python con su conversión de un directorio a otro. Esta opción incluye a la opción `-w` ya que no tendría sentido de otra manera.

Nuevo en la versión 3.2.3: Se agregó la opción `-W`.

La opción `--add-suffix` agrega un texto al final de todos los nombres de archivo. La opción `-n` es necesaria, ya que las copias de respaldo no son necesarias cuando escribimos a un archivo con distinto nombre. Ejemplo:

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

Hará que se escriba una archivo convertido con el nombre `example.py3`.

Nuevo en la versión 3.2.3: Se agrega la opción `--add-suffix`.

Para convertir un proyecto entero de un árbol de directorios a otro use:

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

## Fixers

Cada paso de la transformación del código es encapsulado en un fixer. El comando `2to3 -l` los lista. Como se explicó arriba, cada uno de estos puede habilitarse o deshabilitarse individualmente. En esta sección se los describe más detalladamente.

apply

  Elimina el uso de `apply()`. Por ejemplo `apply(function, *args, **kwargs)` es convertido a `function(*args, **kwargs)`.

asserts

  Reemplaza los nombre de método `unittest` en desuso por los correctos.

  De | A
  --- | ---
  `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

  Convierte `basestring` a `str`.

buffer

  Convierte `buffer` a `memoryview`. Este fixer es opcional porque la API `memoryview` es similar pero no exactamente la misma que la del `buffer`.

dict

  Corrige los métodos de iteración del diccionario, `dict.iteritems()` es convertido a `dict.items()`, `dict.iterkeys()` a `dict.keys()`, y `dict.itervalues()` a `dict.values()`. Del mismo modo, `dict.viewitems()`, `dict.viewkeys()` y `dict.viewvalues()` son convertidos respectivamente a `dict.items()`, `dict.keys()` y `dict.values()`. También incluye los usos existentes de `dict.items()`, `dict.keys()`, y `dict.values()` en una llamada a `list`.

except

  Convierte `except X, T` a `except X as T`.

exec

  Convierte la declaración `exec` a la función `exec()`.

execfile

  Elimina el uso de la función `execfile()`. El argumento para `execfile()` es encapsulado para las funciones `open()`, `compile()`, y `exec()`.

exitfunc

  Cambia la declaración de `sys.exitfunc` para usar el módulo `atexit`.

filter

  Encapsula la función `filter()` usando una llamada para la clase `list`.

funcattrs

  Corrige los atributos de la función que fueron renombrados. Por ejemplo, `my_function.func_closure` es convertido a `my_function.__closure__`.

future

  Elimina la declaración `from __future__ import new_feature`.

getcwdu

  Renombra la función `os.getcwdu()` a `os.getcwd()`.

has_key

  Cambia `dict.has_key(key)` a `key in dict`.

idioms

  Este fixer opcional ejecuta varias transformaciones que tornan el código Python más idiomático. Comparaciones de tipo como `type(x) is SomeClass` y `type(x) == SomeClass` son convertidas a `isinstance(x, SomeClass)`.``while 1`` cambia a `while True`. Este fixer también intenta hacer uso de `sorted()` en los lugares apropiados. Por ejemplo, en este bloque:

      L = list(some_iterable)
      L.sort()

  es convertido a

      L = sorted(some_iterable)

import

  Detecta las importaciones entre hermanos y las convierte en importaciones relativas.

imports

  Maneja los cambios de nombre de módulo en la librería estándar.

imports2

  Maneja otros cambios de nombre de módulo en la biblioteca estándar. Está separada del fixer `imports` solo por motivos de limitaciones técnicas.

input

  Convierte `input(prompt)` a `eval(input(prompt))`.

intern

  Convierte `intern()` a `sys.intern()`.

isinstance

  Corrige tipos duplicados en el segundo argumento de `isinstance()`. Por ejemplo,``isinstance(x, (int, int))`` es convertido a `isinstance(x, int)` y `isinstance(x, (int, float, int))` es convertido a `isinstance(x, (int, float))`.

itertools_imports

  Elimina importaciones de `itertools.ifilter()`, `itertools.izip()`, y `itertools.imap()`. Importación de `itertools.ifilterfalse()` también se cambian a `itertools.filterfalse()`.

itertools

  Cambia el uso de `itertools.ifilter()`, `itertools.izip()`, y `itertools.imap()` para sus equivalentes integrados `itertools.ifilterfalse()` es cambiado a `itertools.filterfalse()`.

long

  Renombra `long` a `int`.

map

  Encapsula `map()` en una llamada a `list`. También cambia `map(None, x)` a `list(x)`. Usando `from future_builtins import map` se deshabilita este fixer.

metaclass

  Convierte la vieja sintaxis de metaclase (`__metaclass__ = Meta` en el cuerpo de la clase) a la nueva sintaxis (`class X(metaclass=Meta)`).

methodattrs

  Corrige nombres de atributos de métodos antiguos. Por ejemplo, `meth.im_func` is convertido a `meth.__func__`.

ne

  Convierte la antigua sintaxis no-igual, `<>`, a `!=`.

next

  Convierte el uso de métodos iteradores `next()` para la función `next()`. También renombra métodos `next()` a `__next__()`.

nonzero

  Renombradas las definiciones de los métodos llamados `__nonzero__()` a `__bool__()`.

numliterals

  Convierte literales octales a la nueva sintaxis.

operator

  Convierte llamadas para varias funciones en el módulo `operator` a otras, pero equivalentes, llamadas de funciones. Cuando es necesario, se agregan las declaraciones `import` apropiadas, por ejemplo `import collections.abc`. Se realizan los siguientes mapeos:

  De | A
  --- | ---
  `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

  Agrega los paréntesis extra donde sean necesarios en las listas de comprensión. Por ejemplo `[x for x in 1, 2]` se convierte en `[x for x in (1, 2)]`.

print

  Convierte la declaración `print` en la función `print()`.

raise

  Convierte `raise E, V` a `raise E(V)`, y `raise E, V, T` a `raise E(V).with_traceback(T)`. SI `E` es una tupla, la conversión será incorrecta porque sustituir tuplas por excepciones fue eliminado en Python 3.0.

raw_input

  Conviertes `raw_input()` to `input()`.

reduce

  Maneja el movimiento de `reduce()` a `functools.reduce()`.

reload

  Convierte `reload()` a `importlib.reload()`.

renames

  Cambia `sys.maxint` a `sys.maxsize`.

repr

  Sustituye el backtick repr por la función `repr()`.

set_literal

  Sustituye el uso de la clase constructora `set` por su literal. Este fixer es opcional.

standarderror

  Renombra `StandardError` a `Exception`.

sys_exc

  Cambia los `sys.exc_value`, `sys.exc_type`, `sys.exc_traceback` en desuso para usar la función `sys.exc_info()`.

throw

  Corrige el cambio de la API en el método generador `throw()`.

tuple_params

  Elimina el desempaquetamiento implícito del parámetro de tupla. Este fixer inserta variables temporarias.

types

  Corrige el código roto por la remoción de algunos miembros en el módulo `types`.

unicode

  Renombra `unicode` a `str`.

urllib

  Maneja el renombramiento de los módulos `urllib` y `urllib2` para el paquete `urllib`.

ws_comma

  Remueve el exceso de espacios blancos de los ítems separados por coma. Este fixer es opcional.

xrange

  Renombra `xrange()` a `range()` y encapsula la llamada a la función existente `range()` con `list`.

xreadlines

  Cambia `for x in file.xreadlines()` por `for x in file`.

zip

  Encapsula el uso de la función `zip()` en una llamada a la clase `list`. Esto está deshabilitado cuando `from future_builtins import zip` aparece.

## `lib2to3` — biblioteca 2to3

Código fuente: Lib/lib2to3/

Obsoleto desde la versión 3.11, se eliminará en la versión 3.13: Python 3.9 cambió a un analizador PEG (consulte PEP 617) mientras que lib2to3 usa un analizador LL (1) menos flexible. Python 3.10 incluye una nueva sintaxis de lenguaje que el analizador LL (1) de lib2to3 no puede analizar (consulte PEP 634). El módulo `lib2to3` se marcó como pendiente de ser obsoleto en Python 3.9 (aumentando `PendingDeprecationWarning` en la importación) y completamente obsoleto en Python 3.11 (aumentando `DeprecationWarning`). Se eliminará de la biblioteca estándar en Python 3.13. Considere alternativas de terceros como LibCST o parso.

Nota

La API del módulo `lib2to3` debe considerarse inestable y puede cambiar drásticamente en el futuro.