online - python 2to3 install ubuntu
Python 2 y Python 3 desarrollo dual (6)
Estoy comenzando un nuevo proyecto de Python, e idealmente me gustaría ofrecer soporte Python 2 y 3 desde el principio, con una mínima carga de desarrollo. Mi pregunta es, ¿cuál es la mejor manera de hacer esto para nuevos proyectos?
He encontrado proyectos que ejecutan 2to3 o incluso 3to2, como parte de su script de instalación. Esta parece ser una forma muy común. Sin embargo, parece haber varias formas diferentes de hacer esto. También me encontré con Distribute .
También existe la opción de intentar escribir código Polyglot Python 2 / Python 3. Aunque esto parece una idea horrible, me he dado cuenta de que tiendo a escribir código últimamente que es más idiomático que el código Python 3, aunque todavía lo ejecuto como Python 2. Tengo la sensación de que esto solo ayuda a mi propia transición cuando el finalmente llega el día, y no hace mucho por ofrecer o al menos ayudar con soporte dual.
La mayoría de los proyectos que ofrecen soporte dual que he visto agregan soporte de Python 3 tarde, por lo que estoy especialmente curioso si hay una mejor manera que sea más adecuada para nuevos proyectos, donde tiene el beneficio de una borrón y cuenta nueva.
¡Gracias!
Actualización: Gracias a todos, aquí hay un resumen de las sugerencias:
Polyglot (los mismos archivos de código fuente se ejecutan en Python 2 y 3)
- Usa six
- Especialmente viable si no necesita soporte para versiones bajas de 2. *
- Nadie sugirió esto, pero
from __future__ import ...
para darle el comportamiento de Python 3 con un modesto requisito de Python 2. * (por ejemplo, la división de Python 3 ha estado disponible desde Python 2.2). Esto es especialmente aplicable para el nuevo proyecto, ya que ayuda si toma esta decisión desde el principio. - Si su código específico de Python 3 es muy raro, puede buscar
sys.version_info >= (3,)
y básicamente hacer lo que hace seis, pero de forma ad-hoc.
Conversión automática
- Ejecute 2to3 o 3to2 automáticamente en
setup.py
- Use Distribute para hacer esto por usted (Distribuir es un proyecto de un solo archivo que puede incluirse fácilmente en su proyecto para evitar otro requisito, como se menciona here )
- Confíe en las pruebas unitarias para asegurarse de que la conversión sea correcta
Para ver videos sobre cómo lidiar con Unicode y hora / fecha, consulte la respuesta de Paulo Scardine .
Debería verificar six , una biblioteca que proporciona una interfaz unificada para varias cosas que difieren entre Python 2 y 3.
Elige 2 o 3, cualquiera que sea tu sabor favorito, y haz que funcione muy bien en eso, con pruebas unitarias. Luego, asegúrese de que esas pruebas funcionen después de ejecutarlo a través de py2to3 o py3to2. Mejor mantener una versión de código.
En mi experiencia, depende del tipo de proyecto.
Si se trata de una biblioteca o una aplicación muy autónoma, se desarrolla una opción común en Python 2.7, evitando las construcciones desaprobadas en Python 3.x tanto como sea posible y recurriendo a pruebas automatizadas para identificar agujeros dejados por py2to3 que deberá corregir manualmente.
Por otro lado, para aplicaciones de la vida real, prepárese para tropezar constantemente con las bibliotecas que aún no se han migrado a py3k (algunas veces importantes). La mayoría de las veces no tendrá más remedio que portar la biblioteca a Python 3, por lo que si puede pagar eso, vaya por ello. Normalmente no puedo, es por eso que no estoy apoyando Python 3 para este tipo de proyecto (pero me cuesta escribir código que será más fácil de transportar cuando sea oportuno).
Para el manejo de unicode, encontré este video de PyCon 2012 muy informativo. El consejo es bueno tanto para Python 2.xy 3.x: trate cada cadena proveniente del exterior como bytes y conviértala a unicode lo más pronto posible y las cadenas de salida se convertirán a bytes lo más tarde posible. Hay otro video muy informativo sobre el manejo de la fecha / hora .
En mi experiencia, es mejor no usar una biblioteca como six
; En su lugar, tengo un solo compat.py
para cada paquete con solo el código necesario, no muy diferente al enfoque de Scott Griffiths . six
también tiene la carga de tratar de soportar las versiones de Python ya desaparecidas: la verdad es que la vida es mucho más fácil cuando se acepta que las Pitones <= 2.6 y <= 3.2 han desaparecido. En 2.7 hay características de compatibilidad con backported, como los métodos .view*
en dict
s que funcionan exactamente como sus versiones sin prefijo en Python 3; y Python 3.3, por otro lado, admite el prefijo u
en cadenas unicode nuevamente.
Incluso para paquetes muy sustanciales, un módulo compat.py
, que permite que otros códigos funcionen sin cambios, puede ser bastante breve: aquí hay un ejemplo del paquete pika
que mis colegas y yo ayudamos a hacer 2/3 políglotas. Pika es uno de esos proyectos que realmente han mezclado elementos internos que mezclan cadenas de 8 bits y unicode entre sí, pero ahora lo hemos usado en producción en Python 3 durante más de 6 meses sin problemas.
Otra cosa importante es usar siempre los siguientes __future__
s al desarrollar:
from __future__ import absolute_import, division, print_function
Recomiendo no usar unicode_literals
, porque hay algunas cadenas que deben ser del tipo llamado str
en cualquiera de las plataformas. Si no utiliza unicode_literals
, puede hacer lo siguiente:
-
b''123''
es el literal de cadena de 8 bits -
''123''
es del tipostr
en ambas plataformas -
u''123''
es texto unicode apropiado en ambas plataformas
En cualquier caso, no haga 2to3 en la instalación / tiempo de compilación del paquete; algunos paquetes solían hacer eso en el pasado; la pip install
de esos paquetes tomó algunos segundos en Python 2, pero más cerca de minutos en Python 3.
Mi experiencia personal ha sido que es más fácil escribir código que funcione sin cambios tanto en Python 2 como en 3, en lugar de confiar en las secuencias de comandos 2to3 / 3to2, que a menudo no consiguen la traducción correcta.
Tal vez mi situación es inusual ya que estoy haciendo muchas cosas con los tipos de bytes y 2to3 tiene una tarea difícil para convertirlos, pero la conveniencia de tener una base de código más grande que la maldad de tener unos pocos hacks en el código.
Como ejemplo concreto, mi módulo bitstring fue una conversión temprana a Python 3 y el mismo código se usa para Python 2.6 / 2.7 / 3.x. La fuente es más de 4000 líneas de código y este es el bit que necesitaba para que funcionara para las diferentes versiones principales:
# For Python 2.x/ 3.x coexistence
# Yes this is very very hacky.
try:
xrange
for i in range(256):
BYTE_REVERSAL_DICT[i] = chr(int("{0:08b}".format(i)[::-1], 2))
except NameError:
for i in range(256):
BYTE_REVERSAL_DICT[i] = bytes([int("{0:08b}".format(i)[::-1], 2)])
from io import IOBase as file
xrange = range
basestring = str
OK, eso no es bonito, pero significa que puedo escribir el 99% del código en un buen estilo de Python 2 y todas las pruebas de unidades aún pasan por el mismo código en Python 3. Esta ruta no es para todos, pero es una opción a considerar.
Si necesita soporte para Python 2.5 o anterior, usar Distribute y su integración 2to3 es generalmente la mejor manera de hacerlo. Pero si solo necesita soportar Python 2.6 o posterior, haría que el código se ejecute en Python 2 y Python 3 sin conversión. También usaría las six bibliotecas para hacer esto más fácil.