Pour la conversion de code Python2 en Python3, quelle version de Python et Django convient le mieux?


11

Actuellement, je travaille dans une grande entreprise où nous devons convertir un ancien grand projet Django de python2 en version python3, donc j'ai fait beaucoup de recherches liées mais je ne parviens toujours pas à trouver de réponse parfaite concernant la version de Python et Django la mieux adaptée à la conversion.

Actuellement, j'utilise Python: 2.7.16 et Django: 1.9.13 dans mon ancienne version.

Tout le monde peut me suggérer la version la mieux adaptée de Python et Django pour l'ancienne version ci-dessus pour la conversion de python2 en python3.


La version actuelle de python3 est Python 3.8 et la dernière version de Django est Django 3.0. Le site Web de Django recommande la dernière version de python 3 , qui est 3.8. Y a-t-il une raison particulière pour laquelle vous ne souhaitez pas accélérer à la fois python et django vers leurs versions les plus récentes?
Green Cloak Guy

2
Pour l'anecdote, j'ai réalisé il y a quelques jours à peine que le site Web basé sur Django que je maintiens depuis quelques années fonctionne actuellement sur le serveur sur lequel il est hébergé en utilisant python2.7, alors que je l'ai exécuté localement en utilisant python3. 7. La seule différence que j'ai trouvée, c'est lorsque j'ai essayé d'utiliser des chaînes f quelque part pour la première fois et que la version du serveur Web s'est bloquée; sinon, il fonctionne exactement comme prévu (exactement le même) localement et à distance, à des fins de test et d'ajout de fonctionnalités. Ma conclusion entièrement anecdotique est que Django est généralement compatible avec la plupart des choses.
Green Cloak Guy

1
pour la dernière version, j'ai trouvé que certaines personnes ne le recommandent pas car dans la dernière version, si vous avez un problème lié aux nouvelles mises à jour, il sera parfois difficile de trouver une solution, donc dans le projet actuel, je ne veux pas faire ce genre de risque et aussi pour En testant l'objectif, j'ai commencé à convertir mon projet en python 3.7.3 avec la dernière version de Django et j'ai déjà trouvé 30 types de problèmes.
Lune du

Il convient de noter - cette question a été soulevée lors d'un audit de révision pour moi. «Y a-t-il un document ou une référence» est très clairement hors sujet (demander une ressource hors site). Cependant, je pense que la question pourrait être modifiée de manière à mieux conduire à la réponse acceptée ci-dessous.
theMayer

Réponses:


3

Je pensais ajouter un peu à la stratégie préconisée par la réponse de Wim - obtenir la version appropriée de Django fonctionnant à la fois sur 2.7 et 3.x - et décrire quelques tactiques qui ont fonctionné pour moi.

Python 2.7 est votre capsule d'échappement, jusqu'à ce que vous appuyiez sur la gâchette sur 3.x

  • vos tests doivent s'exécuter sur les deux
  • n'utilisez pas de fonctionnalités spécifiques à 3.x, comme les chaînes f
  • d'abord Python 3.x, puis seulement plus tard Django 2.x qui ne fonctionne pas sur 2.7
  • commencer tôt, ne pas trop analyser, mais éviter l'approche du big bang
    • fichier par fichier au début.
    • commencez par le code de niveau le plus bas, comme les bibliothèques d'utilitaires, pour lequel vous disposez de suites de tests.
    • si possible, essayez de fusionner progressivement vos modifications dans les branches de production 2.7 et de garder votre code de portage 3.x à jour avec les changements de prod.

Avec quelle version mineure de Django commencer?

Mon critère ici est que les migrations Django peuvent être assez impliquées (et nécessitent en fait plus de réflexion que 2 => 3 travaux). Je passerais donc à la version 1.11 la plus récente et la plus efficace de cette façon, vous apportez déjà une certaine valeur à vos utilisateurs 2.7. Il y a probablement un bon nombre de cales de compatibilité pré-2.x sur 1.11 et vous obtiendrez ses avertissements de dépréciation 2.x.

Quelle version mineure de Python 3.x pour commencer?

Il est préférable de prendre en compte tous les angles, tels que la disponibilité de vos bibliothèques tierces, la prise en charge de votre suite CI / devops et la disponibilité sur vos images de système d'exploitation de serveur choisies. Vous pouvez toujours installer 3.8 et essayer une installation pip de votre requirements.txt par lui-même, par exemple.

Effet de levier git (ou tout ce que vous utilisez Scm) et virtualenv .

  • des requirement.txtfichiers séparés , mais ...
  • si vous avez un dépôt git basé sur un fichier, vous pouvez pointer chaque venv sur la même ligne de code avec un pip install -e <your directory>. cela signifie que, dans 2 terminaux différents, vous pouvez exécuter 2.7 et 3.x contre les mêmes unités.
  • vous pouvez même exécuter les serveurs Django 2.7 et 3.x côte à côte sur différents ports et indiquer Firefox et Chrome.
  • engagez-vous souvent (sur la branche de portage au moins) et découvrez git bisect .

utiliser 2to3

Oui, il cassera le code 2.7 et Django si vous le laissez. Donc...

  • exécutez-le en mode aperçu ou sur un seul fichier. voir ce qu'il casse mais aussi voir ce qu'il a bien fait.

  • limitez-le à certaines conversions qui ne cassent pas 2.7 ou Django. print x=> print (x)et except(Exception) as esont 2 évidents.

Voici à quoi ressemblait ma commande étranglée:

2to3 $tgt -w -f except -f raise -f next -f funcattrs -f print
  • exécutez-le fichier par fichier jusqu'à ce que vous soyez vraiment confiant.

utilisez sed ou awk plutôt que votre éditeur pour les conversions en masse.

L'avantage est que, lorsque vous devenez plus conscient des préoccupations spécifiques de vos applications, vous pouvez créer une suite de modifications qui peuvent être exécutées sur 1 fichier ou plusieurs fichiers et faire la plupart du travail sans casser 2.7 ou Django. Appliquez ceci après votre passage 2to3 convenablement étranglé . Cela vous laisse des nettoyages résiduels dans votre éditeur et la réussite de vos tests.

(facultatif) commencez à courir en noir sur le code 2.7.

black qui est un formateur de code, utilise Python 3 ASTs pour exécuter son analyse. Il n'essaie pas d'exécuter le code, mais il signalera les erreurs de syntaxe qui l'empêcheront de passer à l'étape AST. Vous devrez travailler avec de la magie globale pour installer pip pour y arriver et vous devez acheter l'utilité des noirs.

D'autres l'ont fait - apprenez d'eux.

Écouter # 155 Les étapes pratiques pour passer à Python 3 devraient vous donner quelques idées sur le travail. Regardez les liens d'exposition pour cela. Ils aiment parler du mouvement Instagram (?) Qui impliquait un ajustement progressif de l'exécution du code 2.7 à la syntaxe 3.x sur une base de code commune et sur la même branche git, jusqu'au jour du déclenchement.

Voir aussi The Conservative Python 3 Porting Guide

et Instagram se déplacent en douceur vers Python 3 - La nouvelle pile

Conclusion

Votre temps pour Django 1.11 EOL (avril 2020) est assez court, donc si vous avez plus de 2 ressources de développement à y jeter, j'envisagerais de faire ce qui suit en parallèle:

  • DEV # 1: commencez par une bosse Django 1.11 (la théorie étant que Django 1.11 est probablement mieux positionné comme point de départ pour Django 2.x), en utilisant 2.7.

  • DEV # 2: lancez-vous sur Python 3.6 / 3.7 de votre code utilitaire non-Django. Étant donné que le code est compatible 2.7 à ce stade, fusionnez-le dans # 1 au fur et à mesure.

Découvrez comment les deux tâches se déroulent, évaluez le risque lié au projet lié à Django et à quoi ressemble la douleur Python 3. Vous manquez déjà le Python 2.7 EOL, mais un framework web obsolète est probablement plus dangereux que l'héritage Python 2.7, au moins pendant quelques mois. Je n'attendrais donc pas trop longtemps pour commencer à migrer depuis Django 1.9 et votre travail ne sera pas perdu. À mesure que vous voyez les progrès, vous commencerez à mieux voir les risques du projet.

Votre progression initiale en 2to3 sera lente, mais l'outillage et les conseils sont suffisamment bons pour que vous preniez rapidement de la vitesse, alors ne pensez pas trop avant de commencer à acquérir de l'expérience. Le côté Django dépend de votre exposition aux changements de rupture dans le framework, c'est pourquoi je pense qu'il est préférable de commencer tôt.

PS (opinion controversée / personnelle) Je n'ai pas beaucoup utilisé six bibliothèques de ponts 2 à 3 en conserve.

Ce n'est pas parce que je ne lui fais pas confiance - c'est génial pour les bibliothèques tierces - mais plutôt que je ne voulais pas ajouter une dépendance permanente complexe (et j'étais trop paresseux pour lire son doc). J'avais écrit du code 2.7 dans une syntaxe compatible 3.x pendant longtemps, donc je n'ai pas vraiment ressenti le besoin de les utiliser. Votre kilométrage peut varier et ne vous engagez pas sur cette voie si cela vous semble beaucoup de travail .

Au lieu de cela, j'ai créé un py223.py (57 LOC avec commentaires) avec ce type de contenu, dont la plupart concerne les solutions de contournement pour les obsolescences et les changements de nom dans la bibliothèque standard.

try:
    basestring_ = basestring
except (NameError,) as e:
    basestring_ = str

try:
    cmp_ = cmp
except (NameError,) as e:
    # from http://portingguide.readthedocs.io/en/latest/comparisons.html
    def cmp_(x, y):
        """
        Replacement for built-in function cmp that was removed in Python 3
        """
        return (x > y) - (x < y)

Importez ensuite à partir de ce py223 pour contourner ces problèmes spécifiques. Plus tard, je vais juste fossé l'importation et déplacer les étranges isinstance(x, basestr_)pour isinstance(x, str)mais je sais à l' avance il y a peu à craindre.


Bon conseil. Juste une note, Django lui-même utilise déjà sixpour la couche de compatibilité, donc si vous voulez l'utiliser dans un projet Django pendant la transition, alors ce n'est pas "ajouter une dépendance permanente complexe".
wim

@wim. Je suis d'accord avec vous. six, mais cela dépend du point de vue. J'ai déjà noté qu'il est livré avec des bibliothèques tierces, donc il ne "coûte" pas en termes d'exigences et de dépendances globales. Cependant, je - peut-être à tort - le considérais comme une grosse boîte noire / verrue au milieu de mon code. si vous ne faites que tester des chaînes d'instance / unicode / basestring et si vous savez comment le faire vous-même, alors vous savez exactement comment sauvegarder vos shims lorsqu'ils ne sont plus nécessaires. Je vais cependant déplacer cela jusqu'à la fin.
JL Peyret

C'est pip install -e ...(avec une minuscule -e), non?
thebjorn

c'est probablement le cas. corrigera
JL Peyret

3

Ma suggestion est de commencer par mettre à niveau vers Django==1.11.26, qui est la version la plus récente de Django qui prend en charge Python 2 et Python 3. Restez sur votre version actuelle de Python 2.7 pour l'instant.

Lisez attentivement les notes de publication de 1.10.x et 1.11.x, en vérifiant les dépréciations et en corrigeant tout ce qui ne fonctionnait plus à partir de votre code 1.9.x. Les choses vont casser. Django se déplace rapidement. Pour un grand projet Django, de nombreux changements de code peuvent être nécessaires, et si vous utilisez beaucoup de plugins ou de bibliothèques tiers, vous devrez peut-être jongler avec leurs versions. Certaines de vos dépendances tierces auront probablement été entièrement abandonnées, vous devez donc trouver des remplacements ou supprimer les fonctionnalités.

Pour trouver les notes de publication de chaque mise à niveau de version, il suffit de google "Quoi de neuf dans Django". Les hits documenteront méticuleusement toutes les dépréciations et les changements:

Une fois que le webapp semble fonctionner très bien sur Django 1.11, avec tous les tests qui passe (vous faire une suite de tests, non?), Vous pouvez faire la conversion Python 3, tout en conservant la version Django la même chose. Django 1.11 prend en charge jusqu'à Python 3.7, ce serait donc une bonne version à cibler. Attendez-vous à unicode partout, car les conversions implicites entre octets et texte ont maintenant disparu et de nombreuses webapps Python 2 se sont appuyées sur cela.

Une fois que le projet semble fonctionner correctement sur Django 1.11 et Python 3.7, vous pouvez penser à la mise à niveau vers Django 3.0, en suivant le même processus qu'auparavant - lire les notes de publication, apporter les modifications nécessaires, exécuter la suite de tests et vérifier la webapp dans un serveur de développement manuellement.


1
Certainement la voie à suivre. Obtenez votre code de test à exécuter à la fois sur 2.7 et 3.x. Vous pouvez avoir 2 virtualenvs différents pointant vers le même dépôt git avec pip install -E. Une fois les tests unitaires en cours, lancez l'utilisation de Django-on-3x et continuez à travailler le code en 2 et 3. Avec un codage soigneux et en faisant attention de ne pas graver vos ponts 2.7 - pas de chaînes f par exemple - le basculement sera très anticlimactique. Une fois que 3.x est entièrement stable, commencez à utiliser uniquement du code 3.x. L'avantage est que la production 2.7 est toujours en phase jusqu'au basculement.
JL Peyret

2

Je voudrais d'abord passer à py3. Vous devrez regarder setup.pydans le repo de Django sur la branche stable / 1.9.x ( https://github.com/django/django/blob/stable/1.9.x/setup.py ) pour comprendre que le py3 les versions prises en charge sont 3.4 (mortes) et 3.5.

Une fois que vous êtes sur py3.5 et Django 1.9, vous pouvez mettre à niveau un à la fois jusqu'à ce que vous obteniez la version à laquelle vous souhaitez mettre fin. Par exemple, Django 1.11 prend en charge py3.5 et py3.7, donc

py27/dj19 -> py35/dj19 -> py35/dj1.11 -> py37/dj1.11 ... -> py37/dj2.2

dj2.2 est la première version prenant en charge py3.8, mais je m'arrêterais probablement à py37 / dj2.2 si vous travaillez dans un environnement normalement conservateur.

Si vous avez d'autres packages, vous devrez trouver des combinaisons de versions qui fonctionneront ensemble à chaque étape. Avoir un plan est la clé, et la mise à niveau d'un seul composant à la fois finira généralement par vous faire gagner du temps.

La future bibliothèque ( https://python-future.org/ ) vous aidera dans de nombreuses situations délicates pendant que vous avez besoin de code pour fonctionner sur py27 et 3.x. six est super aussi. J'éviterais de rouler votre propre couche de compatibilité (pourquoi réinventer la roue?)

Si possible, essayez d'obtenir une couverture de test unitaire allant de 75 à 85% avant de commencer, et définissez définitivement des tests automatiques sur les versions "de" et "à" pour chaque étape de mise à niveau. Assurez-vous de lire et de corriger tous les avertissements de Django avant de passer à la prochaine version - Django se soucie très peu de la compatibilité descendante, donc je suggère normalement de toucher chaque version mineure sur le chemin de mise à niveau (ou au moins assurez-vous de lire le "à l'envers"). incompatibilités "et listes de dépréciation pour chaque version mineure).

Bonne chance (nous mettons à jour une base de code 300 + Kloc à partir de py27 / dj1.7 en ce moment, donc je ressens votre douleur ;-)


1
+1 sur la couverture du test. C'est une mesure clé ici, quelle que soit l'approche que l'on finit par adopter. Cela aide vraiment lors de l'expérimentation de changements de code omniprésents et je le dis en tant que personne qui n'est pas du tout un aficionado du test TDD Red / Green. Trouvez un moyen de baser vos résultats 2.7 et la mise à niveau devient beaucoup plus facile.
JL Peyret

2

J'ai le même genre de problème avec mon projet et j'ai essayé python 3.7.5 avec Django version 2.2.7.

Vous ne devriez pas opter pour la dernière version 3.8 de python ou la dernière version 3.0 de Django car il est possible que, pour tout type de bogue, vous ne puissiez pas obtenir la solution appropriée pour les dernières versions.


Cela devrait être un commentaire
Bruno

-2

Vous devriez essayer de tirer pour les versions actuelles. Python 3.8 et Django 3.0. La bibliothèque Six aidera à certains changements de convention. Dans tous les cas, vous allez devoir refaire du refactoring afin de le mettre à jour.


3
Avez-vous déjà effectué une mise à niveau de Django? C'est juste un vœu pieux. Passer directement à Python 3.8 et Django 3.0 à partir de 2.7 / 1.9 sera pratiquement impossible. Même la mise à niveau de versions mineures comme Django 1.9 vers 1.10 peut être un processus difficile, avec de nombreuses modifications de code nécessaires.
wim

Oui, j'ai accordé le luxe et l'approbation de temps pour faire un refactor complet et mettre la demande à jour. Encore une fois, la taille, la logique et les contraintes de temps de l'application sont un problème énorme pour la plupart des gars, mais ils n'ont jamais mentionné la taille de l'application ou la contrainte de temps, j'ai donc recommandé mon avis sur la "meilleure solution" ou "les vœux pieux";)
Dave

De plus, si vous devez vous soucier de choses Ansible et qu'il fonctionne également sur un Ubuntu LTS, vous constaterez que même le support 3.7 manque sur Ubuntu 18.04. Les podcasts de sécurité que j'écoute conseillent de laisser le 3,8 s'installer un peu jusqu'à une libération ponctuelle ou 2 -1 pour des risques inutiles.
JL Peyret

Des bonnes recommandations de podcast de sécurité?
Dave

Pour Python sec, listennotes.com/podcasts/talk-python-to-me/… Mais je pense que le méfiez-vous de la version 3.8-for-a-while est plus récent. Risky Business est un bon podcast de sécurité divertissant, surtout si vous suivez les relations internationales. Toutes mes excuses pour le downvote, mais oui, ce qui a fonctionné dans votre cas pourrait viser quelqu'un d'autre dans un contexte différent. Pour la conversion de 2 à 3, voir listennotes.com/podcasts/talk-python-to-me/…
JL Peyret
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.