Trucos para pasar tu codigo python 2.7 a 3.7 o superior

¡Hola! ¿Estás interesado en hacer la transición de tu código Python 2.7 a Python 3.7 o superior? Pues has llegado al lugar indicado. A lo largo de este artículo, te voy a mostrar diferentes trucos que te facilitarán esta tarea que puede parecer desalentadora. No te preocupes, lo haremos paso a paso. Y lo más importante, aprenderás a hacerlo de una manera sencilla y eficaz. ¡Vamos allá!

Entendiendo las Diferencias entre Python 2 y Python 3

Antes de que nos metamos de lleno en los trucos para hacer la migración de Python 2 a Python 3, es fundamental que comprendas las diferencias clave entre estas dos versiones. Python 3 introduce cambios en el lenguaje que no son compatibles hacia atrás. Este es el motivo principal por el que el proceso de migración puede ser complicado.

Por ejemplo, en Python 2, el comando print se usa sin paréntesis, mientras que en Python 3, se necesita incluir paréntesis. En Python 2.7 podrías usar:

print "¡Hola, mundo!"

En Python 3.7 o superior, debes escribirlo así:

print("¡Hola, mundo!")

El Uso de Librerías Específicas de Python 3

Python 3 trae consigo una serie de nuevas bibliotecas que no están disponibles en Python 2.7. Por lo tanto, deberás cambiar tus importaciones para que coincidan con las bibliotecas de Python 3. Por ejemplo, si antes usabas urlib2, ahora tendrás que importar urllib.request, urllib.parse, y urllib.error.

Aquí te dejo un ejemplo de cómo debería quedar tu código:

# Python 2.7
import urllib2
response = urllib2.urlopen('http://python.org/')
html = response.read()

# Python 3.7
import urllib.request
response = urllib.request.urlopen('http://python.org/')
html = response.read()

Cambio en la Sintaxis de las Excepciones

Uno de los cambios más notables entre Python 2 y Python 3 es cómo se manejan las excepciones. En Python 2, se utilizaba la sintaxis except Exception, e:. Pero en Python 3, debes cambiarlo a except Exception as e:. Aquí puedes ver un ejemplo de cómo hacerlo:

# Python 2.7
try:
    ...
except Exception, e:
    print e

# Python 3.7
try:
    ...
except Exception as e:
    print(e)

La Función map()

La función map() en Python 2 retorna una lista, mientras que en Python 3 retorna un objeto iterable. Así que si quieres obtener una lista como resultado, deberás convertir explícitamente el resultado a una lista usando la función list(). Aquí tienes un ejemplo:

# Python 2.7
result = map(func, values)

# Python 3.7
result = list(map(func, values))

Lidiando con la División en Python

En Python 2, la división de dos enteros da como resultado otro entero. En Python 3, sin embargo, el resultado es un número flotante. Si quieres mantener el comportamiento de Python 2, puedes utilizar el operador «//» para la división entera. Veamos un ejemplo:

# Python 2.7
result = 7 / 2  # Esto da como resultado 3

# Python 3.7
result = 7 / 2  # Esto da como resultado 3.5
result = 7 // 2  # Esto da como resultado 3

La Importancia de __future__

La biblioteca __future__ puede ser tu mejor amiga durante la migración. Esta te permite usar características de Python 3 en tu código Python 2.7, lo que te facilitará mucho la tarea de migración. Por ejemplo, puedes usar la función print() de Python 3 en tu código Python 2.7 de la siguiente manera:

from __future__ import print_function
print("Hola, mundo!")

Comprensión de listas y alcance de las variables

Otro cambio importante en Python 3 es cómo maneja el alcance de las variables en la comprensión de listas. En Python 2, las variables utilizadas en la comprensión de listas se filtraban al alcance principal. Python 3 solucionó este problema encapsulando el alcance de la variable dentro de la comprensión de la lista. Aquí tienes un ejemplo:

# Python 2.7
x = 1
print [x for x in range(5)]
print x  # Esto imprime 4, no 1

# Python 3.7
x = 1
print([x for x in range(5)])
print(x)  # Esto imprime 1

Las claves de los diccionarios son vistas en Python 3

En Python 3, dictionary.keys(), dictionary.values() y dictionary.items() devuelven objetos de vista en lugar de listas. Si necesitas obtener una lista, debes convertir el resultado a una lista de manera explícita. Echa un vistazo al siguiente ejemplo:

# Python 2.7
dictionary = {'uno': 1, 'dos': 2}
keys = dictionary.keys()  # Esto es una lista

# Python 3.7
dictionary = {'uno': 1, 'dos': 2}
keys = list(dictionary.keys())  # Ahora esto es una lista

Adiós a xrange()

En Python 3, la función xrange() fue reemplazada por range(), que ahora retorna un objeto iterable. En Python 2.7, si quieres obtener una lista de range(), debes convertirla explícitamente a una lista:

# Python 2.7
x = xrange(10)  # Esto es un iterable

# Python 3.7
x = list(range(10))  # Esto es una lista

Códigos de Escape en las cadenas de caracteres

Python 2 permite el uso de códigos de escape en cadenas de caracteres no formateadas, mientras que Python 3 no lo permite. Si quieres usar códigos de escape en Python 3, debes usar cadenas de caracteres formateadas. Aquí te muestro cómo hacerlo:

# Python 2.7
x = '\100'

# Python 3.7
x = r'\100'

La función input()

En Python 2, input() evalúa la entrada del usuario, lo que puede ser un problema de seguridad. En Python 3, input() simplemente lee la entrada del usuario como una cadena de texto. Si estás migrando de Python 2 a Python 3, debes tener cuidado con este cambio. Aquí tienes un ejemplo de cómo usar input() en Python 3:

# Python 2.7
x = input("Introduce un número: ")  # Esto evalúa la entrada del usuario

# Python 3.7
x = input("Introduce un número: ")  # Esto toma la entrada del usuario como una cadena de texto
La función round()

Otra diferencia entre Python 2 y Python 3 es cómo manejan la función round(). En Python 2, round(0.5) redondea al número par más cercano. En Python 3, redondea al número entero más cercano. Aquí tienes un ejemplo:

# Python 2.7
print(round(0.5))  # Esto imprime 0

# Python 3.7
print(round(0.5))  # Esto imprime 1

Cambios en los Operadores de Comparación

En Python 2, podías comparar objetos no ordenables. Python 3 te arrojará una excepción en estos casos. Por lo tanto, debes revisar tu código para asegurarte de que no estás intentando comparar objetos no ordenables. Por ejemplo:

# Python 2.7
print(1 < '1')  # Esto es True

# Python 3.7
print(1 < '1')  # Esto arroja una excepción TypeError
Uso de next()

La función next() se usa para obtener el siguiente elemento de un iterador. En Python 2, podías usar el método iterator.next(). En Python 3, debes usar la función next(iterator). Aquí tienes un ejemplo:

# Python 2.7
iterator = iter([1, 2, 3])
print iterator.next()  # Esto imprime 1

# Python 3.7
iterator = iter([1, 2, 3])
print(next(iterator))  # Esto imprime 1

Codificación por Defecto

Python 2 usa ASCII como codificación por defecto, mientras que Python 3 usa UTF-8. Esto puede causar problemas si tu código Python 2 maneja cadenas de caracteres que no son ASCII. Aquí te muestro cómo puedes manejar esto en Python 3:

# Python 2.7
cadena = '¡Hola, mundo!'

# Python 3.7
cadena = '¡Hola, mundo!'

¿__eq__() o __cmp__()?

En Python 2, podías implementar el método __cmp__() en tus clases para realizar comparaciones entre objetos. Python 3 elimina este método y en su lugar debes implementar los métodos __eq__() y __lt__() para la igualdad y la comparación respectivamente. Aquí tienes un ejemplo:

# Python 2.7
class Test(object):
    def __cmp__(self, other):
        return self.value - other.value

# Python 3.7
class Test(object):
    def __eq__(self, other):
        return self.value == other.value

    def __lt__(self, other):
        return self.value < other.value

Cambios en las Variables de Clase

En Python 2, las variables de clase son accesibles a través de la instancia de la clase. En Python 3, no se pueden cambiar las variables de clase a través de la instancia. Por lo tanto, si estás migrando tu código de Python 2 a Python 3, debes tener esto en cuenta. Aquí te dejo un ejemplo:

# Python 2.7
class Test(object):
    value = "Hola, mundo!"
    
    def change_value(self, new_value):
        self.value = new_value

test = Test()
test.change_value("¡Adiós, mundo!")
print(test.value)  # Imprime: ¡Adiós, mundo!

# Python 3.7
class Test(object):
    value = "Hola, mundo!"
    
    def change_value(self, new_value):
        self.value = new_value

test = Test()
test.change_value("¡Adiós, mundo!")
print(test.value)  # Imprime: Hola, mundo!
print(Test.value)  # Imprime: ¡Adiós, mundo!

Añadiendo *args y **kwargs en los Métodos de las Clases

Python 2 permite que los métodos de las clases acepten un número arbitrario de argumentos posicionales y de palabras clave, incluso si no están definidos en el método. Python 3 no permite esto, por lo que debes asegurarte de incluir *args y **kwargs en la definición del método si quieres que acepte un número arbitrario de argumentos. Veamos un ejemplo:

# Python 2.7
class Test(object):
    def method(self, x):
        print(x)

test = Test()
test.method(1, 2, 3)  # Esto es válido

# Python 3.7
class Test(object):
    def method(self, x, *args, **kwargs):
        print(x, args, kwargs)

test = Test()
test.method(1, 2, 3)  # Esto es válido

Los Iteradores en Python 3

En Python 2, los métodos dict.iterkeys(), dict.itervalues() y dict.iteritems() devuelven iteradores. Python 3 los reemplaza por dict.keys(), dict.values() y dict.items(), que devuelven vistas de diccionario. Pero no te preocupes, porque estos también son iterables y puedes convertirlos a listas si es necesario.

# Python 2.7
dictionary = {'uno': 1, 'dos': 2}
for key in dictionary.iterkeys():
    print(key)

# Python 3.7
dictionary = {'uno': 1, 'dos': 2}
for key in dictionary.keys():
    print(key)

Con todos estos trucos, estoy seguro de que tu migración de Python 2.7 a Python 3.7 será más sencilla. No olvides que migrar tu código a Python 3 no sólo es importante por las mejoras que este ofrece, sino también porque Python 2 ya no se mantiene oficialmente. ¡Buena suerte en tu viaje hacia Python 3!

Deja una respuesta