Para la conversión de código Python2 a Python3, ¿qué versión de Python & Django es la más adecuada?

11

Actualmente estoy trabajando en una gran empresa donde necesitamos convertir el antiguo proyecto Django de python2 a la versión python3, por lo que he investigado mucho pero aún no he podido encontrar una respuesta perfecta relacionada con la versión de Python y Django más adecuada para la conversión.

Actualmente estoy usando Python: 2.7.16 y Django: 1.9.13 en mi versión anterior.

Cualquiera puede sugerirme la versión más adecuada de Python y Django para la versión anterior para la conversión de python2 a python3.

Luna
fuente
La versión actual de python3 es Python 3.8, y la última versión de Django es Django 3.0. El sitio web de Django recomienda la última versión de python 3 , que es 3.8. ¿Hay alguna razón particular por la que no quieres acelerar Python y Django a sus versiones más recientes?
Green Cloak Guy
2
Como anécdota, hace unos días me di cuenta de que el sitio web basado en Django que he mantenido durante algunos años ahora se ejecuta realmente en el servidor en el que está alojado usando python2.7, mientras que lo he estado ejecutando localmente usando python3. 7) La única diferencia que encontré fue cuando intenté usar f-strings en algún lugar por primera vez y la versión del servidor web falló; de lo contrario, se ha estado ejecutando exactamente como se esperaba (exactamente lo mismo) local y remotamente, con el propósito de probar y agregar funciones. Mi conclusión completamente anecdótica es que Django es generalmente compatible con la mayoría de las cosas.
Green Cloak Guy
1
para la última versión, he encontrado que algunas personas no recomiendan porque en la última versión si hay algún problema relacionado con las nuevas actualizaciones, a veces será difícil encontrar una solución, por lo que en el proyecto actual no quiero correr ese tipo de riesgo y también para Tras la prueba, comencé a convertir mi proyecto a la última versión de Python 3.7.3 con el último django y ya encontré 30 tipos de problemas.
Luna
Cabe señalar: esta pregunta surgió en una auditoría de revisión para mí. "¿Hay algún documento o referencia" está claramente fuera de tema (pedir un recurso fuera del sitio). Sin embargo, creo que la pregunta podría editarse de tal manera que pudiera conducir mejor a la respuesta aceptada a continuación.
theMayer

Respuestas:

3

Pensé agregar un poco a la estrategia defendida por la respuesta de Wim: obtener la versión adecuada de Django trabajando primero en 2.7 y 3.x, y describir algunas tácticas que funcionaron para mí.

Python 2.7 es tu cápsula de escape, hasta que aprietes el gatillo en 3.x

  • sus pruebas deben ejecutarse en ambos
  • no use ninguna característica específica de 3.x, como f-strings
  • primero Python 3.x, luego solo luego Django 2.x que no se ejecuta en 2.7
  • Comience temprano, no analice en exceso, pero evite el enfoque del Big Bang
    • archivo por archivo al principio.
    • comience con el código de nivel más bajo, como las bibliotecas de utilidades, para las que tiene suites de pruebas.
    • si es posible, intente fusionar gradualmente sus cambios en las ramas de producción 2.7 y mantenga actualizado su código de transferencia 3.x con los cambios de producción.

¿Con qué versión menor de Django para empezar?

Mi criterio aquí es que las migraciones de Django pueden estar bastante involucradas (y en realidad requieren más reflexión que 2 => 3 trabajos). Así que me trasladaría al 1.11 más reciente y mejor de esa manera, ya está proporcionando algo de valor a sus 2.7 usuarios. Probablemente haya una buena cantidad de cuñas de compatibilidad anteriores a 2.x en 1.11 y recibirá sus advertencias de desaprobación 2.x.

¿Con qué versión menor de Python 3.x comenzar?

Es mejor tener en cuenta todos los ángulos, como la disponibilidad de sus librerías de terceros, el soporte de su suite CI / devops y la disponibilidad en las imágenes del sistema operativo de su servidor elegido. Siempre puede instalar 3.8 e intentar una instalación pip de su require.txt solo, por ejemplo.

Aproveche git (o cualquier scm que use) y virtualenv .

  • separar requirement.txtarchivos , pero ...
  • si tiene un repositorio git basado en archivos, puede apuntar cada venv a la misma línea de código con un pip install -e <your directory>. eso significa que, en 2 terminales diferentes, puede ejecutar 2.7 y 3.x contra las mismas pruebas unitarias.
  • incluso podría ejecutar servidores Django 2.7 y 3.x lado a lado en diferentes puertos y señalar, por ejemplo, Firefox y Chrome.
  • comprometerse a menudo (al menos en la rama portadora) y aprender sobre git bisect .

hacer uso de 2to3

Sí, romperá el código 2.7 y Django si lo dejas. Entonces...

  • ejecútelo en modo de vista previa o en un solo archivo. vea lo que se rompe pero también vea lo que hizo bien.

  • limítelo solo a ciertas conversiones que no rompan 2.7 o Django. print x=> print (x)y except(Exception) as eson 2 no-brainers.

Así es como se veía mi comando estrangulado:

2to3 $tgt -w -f except -f raise -f next -f funcattrs -f print
  • ejecútelo archivo por archivo hasta que esté realmente seguro.

use sed o awk en lugar de su editor para conversiones masivas.

La ventaja es que, a medida que se vuelve más consciente de las preocupaciones específicas de sus aplicaciones, puede crear un conjunto de cambios que se pueden ejecutar en 1 archivo o en muchos archivos y hacer la mayor parte del trabajo sin romper 2.7 o Django. Aplique esto después de su pase 2to3 adecuadamente acelerado . Eso te deja con limpiezas residuales en tu editor y haciendo que tus pruebas pasen.

(opcional) comience a ejecutarse en negro en el código 2.7.

black, que es un formateador de código, usa Python 3 AST para ejecutar su análisis. No intenta ejecutar el código, pero marcará los errores de sintaxis que impiden que llegue a la etapa AST. Sin embargo, tendrás que trabajar con la magia global de instalación de pip para llegar allí y debes comprar la utilidad de las negras.

Otras personas lo han hecho, aprende de ellos.

Escuchar # 155 Pasos prácticos para pasar a Python 3 debería darle algunas ideas del trabajo. Mira los enlaces del programa. Les encanta hablar sobre el movimiento de Instagram (?) Que involucró un ajuste gradual de la ejecución del código 2.7 a la sintaxis 3.x en una base de código común y en la misma rama git, hasta el día de apretar el gatillo.

Consulte también la Guía de portabilidad conservadora de Python 3

e Instagram hacen un movimiento suave a Python 3 - The New Stack

Conclusión

Su tiempo para Django 1.11 EOL (abril de 2020) es bastante corto, por lo que si tiene más de 2 recursos de desarrollo para lanzar, consideraría hacer lo siguiente en paralelo:

  • DEV # 1: comience con un golpe Django 1.11 (la teoría es que Django 1.11 probablemente esté mejor posicionado como un punto de partida para Django 2.x), usando 2.7.

  • DEV # 2: comience en Python 3.6 / 3.7 de su código de utilidad que no sea Django. Como el código es compatible con 2.7 en este punto, combínelo en el # 1 a medida que avanza.

Vea cómo proceden ambas tareas, evalúe cuál es el riesgo del proyecto relacionado con Django y cómo se ve el dolor de Python 3. Ya te estás perdiendo la EOL de Python 2.7, pero un marco web obsoleto es probablemente más peligroso que el Python 2.7 heredado, al menos durante unos meses. Por lo tanto, no esperaría demasiado para comenzar a migrar de Django 1.9 y su trabajo al hacerlo no se desperdiciará. A medida que vea el progreso, comenzará a ver mejor los riesgos del proyecto.

Su progreso inicial de 2 a 3 será lento, pero las herramientas y la orientación son lo suficientemente buenas como para que aumente rápidamente la velocidad, así que no piense demasiado antes de comenzar a acumular experiencia. El lado de Django depende de su exposición a cambios importantes en el marco, por lo que creo que es mejor comenzar temprano.

PD (opinión controvertida / personal) No usé seis u otras bibliotecas puente de 2 a 3 enlatadas.

Sus no porque no me fío de ella - es brillante en las librerías de 3 ª parte - sino más bien que no quería añadir una dependencia permanente compleja (y yo era demasiado perezoso para leer su doc). Había estado escribiendo código 2.7 en sintaxis compatible 3.x durante mucho tiempo, así que realmente no sentía la necesidad de usarlos. Su kilometraje puede variar y no se inicie en este camino si parece mucho trabajo .

En cambio, creé un py223.py (57 LOC con comentarios incluidos) con este tipo de contenido, la mayoría de los cuales se refiere a soluciones para desaprobaciones y cambios de nombre en la biblioteca estándar.

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)

Luego importe desde ese py223 para solucionar esas preocupaciones específicas. Más tarde me se acaba de deshacerse de la importación y mover los extraño isinstance(x, basestr_)a isinstance(x, str)pero sé de antemano que hay poco de qué preocuparse.

JL Peyret
fuente
Buen consejo. Solo una nota, Django ya lo usa sixpara la capa de compatibilidad, por lo que si desea usarlo en un proyecto de Django durante la transición, esto no significa "agregar una dependencia permanente compleja".
wim
@wim. Estoy de acuerdo contigo re. seis, pero depende del punto de vista. Ya noté que viene con librerías de terceros, por lo que no "cuesta" en términos de requisitos y dependencias generales. sin embargo, tal vez erróneamente, lo consideré una gran caja / verruga negra en el medio de mi código. Si todo lo que está haciendo es cosas como probar la cadena de instancia / unicode / basetring y si sabe cómo hacerlo usted mismo, entonces sabe exactamente cómo respaldar sus cuñas cuando ya no las necesite. Sin embargo, lo moveré hasta el final.
JL Peyret
Es pip install -e ...(con minúscula -e), ¿verdad?
thebjorn
probablemente lo es. corregirá
JL Peyret
3

Mi sugerencia es actualizar primero a Django==1.11.26 , que es la versión más reciente de Django que es compatible con Python 2 y Python 3. Permanezca en su versión actual de Python 2.7 por ahora.

Lea atentamente las notas de la versión 1.10.xy 1.11.x, compruebe si hay desaprobaciones y arregle todo lo que dejó de funcionar desde su código 1.9.x. Las cosas se romperán. Django se mueve rápido. Para un proyecto grande de Django, es posible que se requieran muchos cambios de código, y si está utilizando una gran cantidad de complementos o bibliotecas de terceros, es posible que tenga que hacer malabarismos con sus versiones. Es probable que algunas de sus dependencias de terceros hayan sido abandonadas por completo, por lo que debe buscar reemplazos o eliminar las funciones.

Para encontrar las notas de la versión para cada actualización de la versión, simplemente busque "Novedades en Django". Los resultados documentarán meticulosamente todas las degradaciones y cambios:

Una vez que la aplicación web parece funcionar bien en Django 1.11, con todas las pruebas aprobadas (lo hace tiene un conjunto de pruebas, verdad?), Entonces puede hacer la conversión de Python 3, manteniendo la versión de Django igual. Django 1.11 admite hasta Python 3.7, por lo que sería una buena versión para apuntar. Espere unicode por todas partes, ya que las conversiones implícitas entre bytes y texto se han ido ahora y muchas aplicaciones web de Python 2 se basaron en eso.

Una vez que el proyecto parece estar funcionando bien en Django 1.11 y Python 3.7, puede pensar en actualizar a Django 3.0, siguiendo el mismo proceso que antes: leyendo las notas de la versión, realizando los cambios necesarios, ejecutando el conjunto de pruebas y revisando la aplicación web en un servidor de desarrollo de forma manual.

wim
fuente
1
Definitivamente el camino a seguir. Haga que su código de prueba se ejecute en 2.7 y 3.x. Puede tener 2 virtualenvs diferentes apuntando al mismo repositorio de git con pip install -E. Una vez que se ejecutan las pruebas unitarias, inicie el uso de prueba de Django-on-3x y vuelva a mantener el código funcionando en 2 y 3. Con una codificación cuidadosa y teniendo cuidado de no quemar sus puentes 2.7, sin cadenas f, por ejemplo, la conmutación será Muy anticlimático. Una vez que 3.x sea completamente estable, comience a usar solo el código 3.x. La ventaja es que la producción 2.7 siempre está en el paso hasta el cambio.
JL Peyret
2

Me actualizaría a py3 primero. Tendrá que mirar setup.pyen el repositorio de Django en la rama estable / 1.9.x ( https://github.com/django/django/blob/stable/1.9.x/setup.py ) para descubrir que el py3 Las versiones admitidas son 3.4 (muerto) y 3.5.

Una vez que esté en py3.5 y Django 1.9, puede actualizar uno a la vez hasta llegar a la versión en la que desea finalizar. Por ejemplo, Django 1.11 admite py3.5 y py3.7, por lo que

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

dj2.2 es la primera versión que admite py3.8, pero probablemente me detendría en py37 / dj2.2 si está trabajando en un entorno normalmente conservador.

Si tiene otros paquetes, necesitará encontrar combinaciones de versiones que funcionen juntas en cada paso. Tener un plan es clave, y actualizar solo un componente a la vez generalmente terminará ahorrándole tiempo.

La futura biblioteca ( https://python-future.org/ ) lo ayudará con muchas situaciones difíciles mientras necesita código para ejecutarse en py27 y 3.x. seis también es genial. Evitaría rodar su propia capa de compatibilidad (¿por qué reinventar la rueda?)

Si es posible, intente obtener una cobertura de prueba de la unidad de hasta el 75-85% antes de comenzar, y definitivamente configure las pruebas automáticas en las versiones "desde" y "a" para cada paso de actualización. Asegúrese de leer y corregir todas las advertencias de Django antes de actualizar a la próxima versión: Django se preocupa muy poco por la compatibilidad con versiones anteriores, por lo que normalmente sugeriría presionar cada versión menor en la ruta de actualización (o al menos asegúrese de leer "al revés" incompatibilidades "y listas de desaprobación para cada versión menor).

Buena suerte (estamos actualizando una base de código de 300+ Kloc desde py27 / dj1.7 en este momento, así que siento tu dolor ;-)

thebjorn
fuente
1
+1 en cobertura de prueba. Esa es una métrica clave aquí, sea cual sea el enfoque que uno tome. Realmente ayuda cuando se experimentan cambios de código generalizados y lo digo como alguien que no es en absoluto un aficionado a las pruebas TDD Red / Green. Encuentre una manera de basar sus resultados 2.7 y la actualización se vuelve mucho más fácil.
JL Peyret
2

Tengo el mismo tipo de problema con mi proyecto y probé Python 3.7.5 con Django versión 2.2.7.

No debe usar la última versión de Python 3.8 o la última versión de Django 3.0 porque puede haber posibilidades de que para cualquier tipo de error no pueda obtener la solución adecuada para las últimas versiones.

Alpesh
fuente
Esto debería ser un comentario
Bruno
-2

Debes intentar disparar para las versiones actuales. Python 3.8 y Django 3.0. La biblioteca Six ayudará con algunos cambios en la convención. De cualquier manera, tendrá que hacer algunas refactorizaciones, por lo que también podría actualizarlas.

Dave
fuente
3
¿Alguna vez has hecho una actualización de Django? Esto es solo una ilusión. Ir directamente a Python 3.8 y Django 3.0 desde 2.7 / 1.9 será prácticamente imposible. Incluso actualizar versiones menores como Django 1.9 a 1.10 puede ser un proceso difícil, con muchos cambios de código necesarios.
wim
Sí, lo hice, dado que tenía la aprobación de lujo y tiempo para hacer una refactorización completa y actualizar la solicitud. Nuevamente, el tamaño de la aplicación, la lógica y las limitaciones de tiempo son un gran problema para la mayoría de los chicos, pero nunca mencionaron el tamaño de la aplicación o la restricción de tiempo, por lo que recomendé mi opinión sobre la "mejor solución" o la "ilusión";)
Dave
Además, si tiene que preocuparse por las cosas Ansible y también se ejecuta en un Ubuntu LTS, encontrará que incluso Ubuntu 3.7 no tiene soporte. Los podcasts de seguridad que escucho aconsejan dejar que 3.8 se instale un poco hasta un lanzamiento puntual o 2. -1 por riesgo innecesario.
JL Peyret
¿Alguna buena recomendación de podcast de seguridad?
Dave
Para Python sec, listennotes.com/podcasts/talk-python-to-me/… Pero creo que la advertencia de 3.8 por un tiempo es más reciente. Risky Business es un podcast de seguridad bueno y entretenido, especialmente si sigue las relaciones internacionales. Disculpas por el voto negativo, pero sí, lo que funcionó en su caso podría afectar a otra persona en un contexto diferente. Para conversiones de 2 a 3, vea listennotes.com/podcasts/talk-python-to-me/…
JL Peyret