Convertir ton code Python 2 en Python 3

Python 2 a atteint la fin de sa vie le 1er janvier 2020. Python 3 est disponible depuis 2008, mais la conversion de 2 à 3 a été lente à cause de dépendances à des bibliothèques qui n’étaient pas disponibles dans Python 3 initialement, les versions antérieures de python 3 étaient plus lentes que python 2 et aussi parce que Python 2 fonctionnait très bien pour de nombreuses personnes. La fin de vie de Python 2 signifie qu’il n’y a plus de versions prises en charge et plus de corrections de bogues de la part de Python. Certaines distributions Linux comme Ubuntu et Red Hat prendront en charge Python 2 pendant un certain temps, mais migrer vers Python 3 est une meilleure solution.

Je pensais que Python 3 était rétrocompatible avec Python 2 ?

Pas à 100 %. Le passage de Python 2 à Python 3 a été l’occasion de « régler » certains problèmes de Python 2. Parmi eux, la promotion d’Unicode de manière plus uniforme dans le langage et la résolution de certains problèmes de syntaxe, comme le fait que print soit une déclaration plutôt qu’une fonction.

Quelques-unes des différences entre Python 2 et Python 3

Plusieurs déclarations telles que print, exec et autres ont été changées en fonctions intégrées. Exemples :

print 'hello world' # valid python 2 not in python 3
print ('hello world') # valid python 3 and later versions of python 2

La division des nombres entiers a également été modifiée. Exemple :

print (5 / 2) # in python 2 result is 2 in python 3 result is 2.5

// a été ajouté à Python 3 pour prendre en charge l’ancien comportement

De nombreuses fonctions renvoient désormais des chaînes unicode/octet dans python 3 au lieu de chaînes ascii/str dans python 2. Exemple :

type (subprocess.checkout_output('cmd')) # returns <class 'bytes'> <class 'bytes'=""> in python 3 vs <type 'str'><type 'str'=""> in python 2

Pour convertir le <class ‘bytes’><class ‘bytes’= » »> de python 3 en une chaîne de caractères, tu dois utiliser l’option .decode(‘ascii’).

type (subprocess.check_output('ls').decode('ascii')) # will result in a <class 'str'><class 'str'=""> in python 3

Certaines bibliothèques ont été réorganisées.

Par exemple, la bibliothèque urllib de Python 2 a été remplacée par urllib de Python 3. Urllib sur Python 3 est également disponible dans des modules tels que urllib.request et urllib.error ; tu peux donc les importer pour obtenir une fonctionnalité similaire à celle de python 2.

from urllib import urlopen # python 2
from urllib.request import urlopen # python 3

Convertir de Python 2 à Python 3 le plus souvent automatiquement

Même si tu peux faire toutes les modifications pour convertir ton script python de python 2 en python 3 à la main, il existe un outil qui fera une grande partie du travail à ta place. 2to3 est un paquet qui peut être installé à partir de la bibliothèque pip et est également disponible en tant que paquet séparé dans les dépôts de nombreuses distributions. Pour installer via pip3

% pip3 install 2to3

Pour installer sur Debian/Ubuntu

% sudo apt install 2to3

Pour installer sur Fedora/CentOS

% sudo yum install 2to3

Remarque : l’installation à partir de pip te permettra d’obtenir la dernière version, alors que les versions des distributions peuvent être un peu plus anciennes, donc l’installation à partir de pip peut être plus efficace pour toi.

Exécuter 2to3

$ 2to3 --help # will provide you the help message from the system

Quelques options intéressantes

-l                  # will provide a list of the fixes available in 2to3.  E.g. print, exec, urllib, and others
-x                  # explicitly not run a transformation, use if one of the "fixes" doesn't work for your code base
-o                  # output dir, put transformed files into another location
--add-suffix=SUFFIX # put a suffix on converted files --add-suffix='3', will convert .py files to .py3 files
-w                  # overwrite current files with modified files

En supposant que tu as un répertoire de code python 2 (scripts) et un dossier de destination pour le code python 3 (scripts3), tu peux faire ce qui suit : La commande pour effectuer la conversion est la suivante

% 2to3 scripts -n -w -o scripts3

Les options sont les suivantes

scripts  - source dir
-n       - no backups
-w       - write-unchanged files, write file even if no changes are required by 2to3
-o       - output directory
scripts3 - output directory, where the converted scripts are written

De cette façon, le code original n’est pas modifié et l’utilisateur peut revoir le code converti dans le dossier scripts3 et continuer à se référer au code original.

Modernize est une enveloppe autour de 2to3

Son comportement est similaire à celui de 2to3, sauf qu’il prend en charge le drapeau –six-unicode qui utilisera les six fonctions d’aide qui permettent de prendre en charge Python 3.1 et Python 3.2. J’utiliserais probablement 2to3 à moins qu’une fonctionnalité convaincante ajoutée à modernize ne t’encourage à l’utiliser. Modernize est également disponible avec certaines distributions comme Debian testing et Arch. Pour installer

# pip3 install modernize

Pour exécuter

# python-modernize --help

Conseils

Dos

Do conversion in small chunks
Do use tools like pylint to help you figure out problematic code, before you convert it
Do compare the code before and after the conversion
Do use the debugger to validate critical code

À ne pas faire

Do not overwrite your code with 2to3, recommend a separate directory
Do not trust in the tools to do everything correctly

Teste, teste, teste

Quelle que soit la façon dont tu convertis ton code de Python 2 à Python 3, tu dois le tester minutieusement. Pour le code Python critique, je te conseille même d’utiliser le débogueur Python pour exécuter le code ligne par ligne.

# python3 -m pdb