2to3: migrando versión de Python con un ejemplo práctico

por | febrero 8, 2018

A Python 2 todavía le quedan cubiertos 2 años de mantenimiento aunque no es mala idea ir revisando nuestros scripts e irlos migrando de forma progresiva, sin prisa pero sin pausa. Lo incluyo entre mis tareas pendientes para los scripts y proyectos que me toca migrar.

Sin ir más lejos en mi repo actual My Tux tengo el script filestrings_modifier.py que copy-pasteo aquí a modo de ejemplo de script escrito en Python 2:

#!/usr/bin/env python2
"""
Author        :Julio Sanz
Website       :www.elarraydejota.com
Email         :juliojosesb@gmail.com
Description   :Script to replace, delete or add strings to a file
Dependencies  :None
Usage         :filestrings_modifier.py [file]
Example       :filestrings_modifier.py mytext.txt
               filestrings_modifier.py /home/mytext.txt
License       :GPLv3
"""

#
# IMPORTS
#

import sys, os

#
# FUNCTIONS
#

def replace_string():
    v_file = sys.argv[1]
    stringtosearch = raw_input("Please specify the text that is going to be replaced --> ")
    replacestring = raw_input("Please specify the text that will replace the word "+stringtosearch+" --> ")
    if os.path.isfile(v_file):
        with open(v_file, 'r') as f:
            data = f.read()
        newdata = data.replace(stringtosearch, replacestring)
        with open(v_file, 'w') as f:
            f.write(newdata)
    else:
        how_to_use()

def how_to_use():
    print "\nWrong usage. Please pass an existing filename (path if needed) as a parameter to the script"
    print "Usage -> filestrings_modifier.py [filename]"
    print "Examples: filestrings_modifier.py mytext.txt"
    print "          filestrings_modifier.py /home/mytext.txt"

# MAIN

if __name__ ==  '__main__':
    if len(sys.argv) == 2:
        replace_string()
    else:
        how_to_use()

Podemos utilizar 2to3 para ayudarnos a migrar este script a Python 3. Primero lanzamos una simulación (el fichero no se modifica) con:

2to3 filestrings_modifier.py

Cuyo resultado será:

...
RefactoringTool: Refactored filestrings_modifier.py
--- filestrings_modifier.py	(original)
+++ filestrings_modifier.py	(refactored)
@@ -23,8 +23,8 @@
 
 def replace_string():
     v_file = sys.argv[1]
-    stringtosearch = raw_input("Please specify the text that is going to be replaced --> ")
-    replacestring = raw_input("Please specify the text that will replace the word "+stringtosearch+" --> ")
+    stringtosearch = input("Please specify the text that is going to be replaced --> ")
+    replacestring = input("Please specify the text that will replace the word "+stringtosearch+" --> ")
     if os.path.isfile(v_file):
         with open(v_file, 'r') as f:
             data = f.read()
@@ -35,10 +35,10 @@
         how_to_use()
 
 def how_to_use():
-    print "\nWrong usage. Please pass an existing filename (path if needed) as a parameter to the script"
-    print "Usage -> filestrings_modifier.py [filename]"
-    print "Examples: filestrings_modifier.py mytext.txt"
-    print "          filestrings_modifier.py /home/mytext.txt"
+    print("\nWrong usage. Please pass an existing filename (path if needed) as a parameter to the script")
+    print("Usage -> filestrings_modifier.py [filename]")
+    print("Examples: filestrings_modifier.py mytext.txt")
+    print("          filestrings_modifier.py /home/mytext.txt")
 
 # MAIN

RefactoringTool: Files that need to be modified:
RefactoringTool: filestrings_modifier.py

Vemos que la utilidad realiza un diff del fichero original y el que quedaría con los cambios propuestos (refactored)

Si quisiéramos cambiar realmente el script utilizamos la opción -w, por ejemplo:

2to3 -w filestrings_modifier.py

Que dicha utilidad nos facilite la vida dándonos pistas sobre cómo migrar nuestros scripts no quita que realicemos tests, comprobaciones y revisión de documentación correspondiente. En este mismo ejemplo que pongo, al migrar el script a Python 3 he tenido que cambiar manualmente el shebang de la cabecera para que apunte a la versión de Python correcta con #!/usr/bin/env python3

Un buen punto de partida de documentación la podemos encontrar en la página pyporting de la web oficial de Python, así como información sobre la utilidad 2to3.

Comparte en: