Necesito hacer que una base de código antigua sea compatible con Python3. El código debe ser compatible con Python2.7 y Python3 durante algunos meses.
Me gustaría agregar esto en el mismo archivo:
# -*- coding: utf-8 -*- from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literalsIntenté esto:
futurize --both-stages --unicode-literals --write --nobackups .Pero esto agrega solo la importación futura de literales Unicode. No las otras importaciones futuras.
Me gustaría evitar escribir mi propio script que agrega esto, ya que agregar esto a ciegas no funciona, ya que algunos archivos ya tienen este encabezado.
Si todo lo que necesita es asegurarse de que el encabezado de codificación del código fuente y las 4 declaraciones de importación estén presentes, la siguiente secuencia de comandos descenderá recursivamente a través de un directorio modificando todos los archivos .py asegurándose de que estas declaraciones requeridas estén presentes. Las actualizaciones se realizarán en su lugar, por lo que sería conveniente asegurarse de tener una copia de seguridad en caso de una falla de hardware en medio de la reescritura de uno de los archivos. Incluso si el código se vuelve a escribir para escribir en un archivo temporal y luego se hace un "movimiento" final para reemplazar el antiguo con el nuevo, el mismo problema persiste.
Primero debe probar esto experimentalmente en un directorio de prueba y, como siempre, UTILIZARLO BAJO SU PROPIO RIESGO.
from pathlib import Path import re root_path = 'absolute_or_releative_path_to_directory' encoding_re = re.compile(r'^# -\*- coding: utf-8 -\*-(\r|\r?\n)') import_re = re.compile(r'\bfrom\s+__future__\s+import\s+((?:absolute_import|division|print_function|unicode_literals))\b') all_imports = ['absolute_import', 'division', 'print_function', 'unicode_literals'] all_imports_set = set(all_imports) for path in Path(root_path).glob('**/*.py'): with open(path, 'r', encoding='utf-8') as f: source = f.read() # Look for source encoding header: m = encoding_re.search(source) # Look for the 4 imports: found_imports = set(import_re.findall(source)) if m and len(found_imports) == 4: # Found encoding line and all 4 imports, # so there is nothing to do: continue # Else we need to write out a replacement file: with open(path, 'w', encoding='utf-8') as f: if not m or len(found_imports) < 4: # Did not find encoding line or we must write out # at least one import. In either case we must write # the encoding line to ensure it is the first line: print('# -*- coding: utf-8 -*-', file=f) if not found_imports: # Found no imports so write out all 4: missing_imports = all_imports else: # Found 1 to 4 import statement; compute the missing ones: missing_imports = all_imports_set - found_imports for import_name in missing_imports: print(f'from __future__ import {import_name}', file=f) # Print remaining source: print(source, end='', file=f)De los documentos :
Solo se agregarán las importaciones
__future__que se consideren necesarias, a menos que se pase la opción de línea de comando--all-importsafuturize, en cuyo caso se agregarán todas.
Si desea futurize para agregar todas esas importaciones incondicionalmente, debe pasarle el indicador --all-imports .
Primero defina una lista de las importaciones que desea que sea cada archivo.
Puede usar el método glob.glob() con el argumento de palabra clave recursive establecido en True para que busque recursivamente archivos .py dentro de una ruta determinada.
Para cada nombre de archivo devuelto, después de leer su contenido, puede usar un filtro para filtrar las importaciones que ya existen en el archivo y solo escribir las que no:
import glob lines = [ "from __future__ import absolute_import", "from __future__ import division", "from __future__ import print_function", "from __future__ import unicode_literals" ] for file in glob.glob('/project/**/*.py', recursive=True): # replace project with the path with open(file, 'r+') as f: content = f.read().splitlines() # Read into a list of lines f.seek(0, 0) # To the top of the file lines2 = [line for line in lines if line not in content] # Filter out existing imports f.write("\n".join(lines2 + content))