Si tengo un script de Python que requiere al menos una versión particular de Python, ¿cuál es la forma correcta de fallar con gracia cuando se usa una versión anterior de Python para iniciar el script?
¿Cómo obtengo el control lo suficientemente temprano como para emitir un mensaje de error y salir?
Por ejemplo, tengo un programa que usa el operador ternery (nuevo en 2.5) y bloques "con" (nuevo en 2.6). Escribí una pequeña rutina de verificación de versión de intérprete que es lo primero que llamaría el script ... excepto que no llega tan lejos. En cambio, el script falla durante la compilación de Python, incluso antes de que se llame a mis rutinas. Por lo tanto, el usuario del script ve algunos rastreos de error de sinax muy oscuros, que requieren que un experto deduzca que es simplemente el caso de ejecutar la versión incorrecta de Python.
Sé cómo verificar la versión de Python. El problema es que cierta sintaxis es ilegal en versiones anteriores de Python. Considere este programa:
import sys
if sys.version_info < (2, 4):
raise "must use python 2.5 or greater"
else:
# syntax error in 2.4, ok in 2.5
x = 1 if True else 2
print x
Cuando se ejecuta por debajo de 2.4, quiero este resultado
$ ~/bin/python2.4 tern.py
must use python 2.5 or greater
y no este resultado:
$ ~/bin/python2.4 tern.py
File "tern.py", line 5
x = 1 if True else 2
^
SyntaxError: invalid syntax
(Canalizando para un compañero de trabajo).
Respuestas:
Puedes probar usando
eval
:Además,
with
está disponible en Python 2.5, solo agreguefrom __future__ import with_statement
.EDITAR: para obtener el control lo suficientemente temprano, puede dividirlo en diferentes
.py
archivos y verificar la compatibilidad en el archivo principal antes de importar (por ejemplo,__init__.py
en un paquete):fuente
exec
lugar deeval
. Se me ocurrió esto al intentar escribir una función que se imprimiera en stderr tanto en py2k como en py3k.import
estación en try / except). Tenga en cuenta que es posible que también necesite verificar otras cosasSyntaxError
(por ejemplo, funciones incorporadas o adiciones a la biblioteca estándar)Tenga un envoltorio alrededor de su programa que haga lo siguiente.
También puede considerar usar
sys.version()
, si planea encontrarse con personas que usan intérpretes de Python anteriores a 2.0, pero luego tiene algunas expresiones regulares que hacer.Y puede haber formas más elegantes de hacer esto.
fuente
sys.version_info
No es una función.import this
. Una encantadora diversión.Tratar
Debería darle una cadena como "2.3.1". Si esto no es exactamente lo que desea, hay un amplio conjunto de datos disponibles a través de la "plataforma" incorporada. Lo que quieras debe estar allí en alguna parte.
fuente
print(platform.python_version())
lugar deplatform.python_version()
!Probablemente la mejor manera de hacer esta comparación de versiones es usar el
sys.hexversion
. Esto es importante porque comparar tuplas de versión no le dará el resultado deseado en todas las versiones de Python.fuente
fuente
sys.version_info
es una tupla con nombre. Deberá usarlo para el número de versión principal y para el menor.sys.version_info[0]
sys.version_info[1]
También puede verificar la versión de Python desde el propio código utilizando el
platform
módulo de la biblioteca estándar.Hay dos funciones:
platform.python_version()
(devuelve cadena).platform.python_version_tuple()
(devuelve tupla).El código de Python
Método fácil para verificar la versión:
También puedes usar el
eval
método:Ejecute el archivo Python en una línea de comando:
La salida de Python con CGI a través de un servidor WAMP en Windows 10:
Recursos útiles
fuente
Los conjuntos se convirtieron en parte del lenguaje central en Python 2.4, para seguir siendo compatibles con versiones anteriores. Hice esto en ese entonces, lo que también funcionará para usted:
fuente
try: set except NameError: from sets import Set as set
Aunque la pregunta es: ¿cómo obtengo el control lo suficientemente temprano como para emitir un mensaje de error y salir ?
La pregunta que respondo es: ¿Cómo obtengo el control lo suficientemente temprano como para emitir un mensaje de error antes de iniciar la aplicación ?
Puedo responderlo de manera muy diferente a las otras publicaciones. Parece que las respuestas hasta ahora están tratando de resolver su pregunta desde Python.
Digo, verifique la versión antes de iniciar Python. Veo que tu camino es Linux o Unix. Sin embargo, solo puedo ofrecerle un script de Windows. Imagino que adaptarlo a la sintaxis de scripting de Linux no sería demasiado difícil.
Aquí está el script de DOS con la versión 2.7:
Esto no ejecuta ninguna parte de su aplicación y, por lo tanto, no generará una excepción de Python. No crea ningún archivo temporal ni agrega ninguna variable de entorno del sistema operativo. Y no finaliza su aplicación con una excepción debido a las diferentes reglas de sintaxis de versión. Esos son tres puntos de acceso de seguridad menos posibles.
La
FOR /F
línea es la clave.Para ver varias versiones de Python, consulte la URL: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17
Y mi versión pirateada:
[Secuencia de comandos MS; Verificación previa de versión de Python del módulo Python] http://pastebin.com/aAuJ91FQ
fuente
recibirá una respuesta como esta
aquí 2.7.6 es la versión
fuente
Como se señaló anteriormente, los errores de sintaxis se producen en tiempo de compilación, no en tiempo de ejecución. Si bien Python es un "lenguaje interpretado", el código de Python no se interpreta directamente; se compila en código de bytes, que luego se interpreta. Hay un paso de compilación que ocurre cuando se importa un módulo (si no hay una versión ya compilada disponible en forma de archivo .pyc o .pyd) y es cuando obtiene su error, no (exactamente) cuando Tu código se está ejecutando.
Puede aplazar el paso de compilación y hacer que suceda en tiempo de ejecución para una sola línea de código, si lo desea, utilizando eval, como se indicó anteriormente, pero personalmente prefiero evitar hacerlo, ya que hace que Python funcione potencialmente compilación innecesaria en tiempo de ejecución, por una parte, y por otra, crea lo que para mí se siente como desorden de código. (Si lo desea, puede generar código que genere código que genere código, y pasar un tiempo absolutamente fabuloso modificando y depurando eso en 6 meses a partir de ahora). Entonces, lo que recomendaría en su lugar es algo más como esto:
.. lo que haría incluso si solo tuviera una función que usara una sintaxis más nueva y fuera muy corta. (De hecho, tomaría todas las medidas razonables para minimizar el número y el tamaño de dichas funciones. Incluso podría escribir una función como ifTrueAElseB (cond, a, b) con esa única línea de sintaxis).
Otra cosa que vale la pena señalar (que estoy un poco sorprendido de que nadie haya señalado todavía) es que, si bien las versiones anteriores de Python no admitían código como
.. soportaba código como
Esa era la vieja forma de escribir expresiones ternarias. Todavía no tengo Python 3 instalado, pero que yo sepa, esa forma "antigua" todavía funciona hasta el día de hoy, por lo que puede decidir por sí mismo si vale la pena usar condicionalmente la nueva sintaxis, si es necesario. para admitir el uso de versiones anteriores de Python.
fuente
a and b or c
lugar deb if a else c
, no es equivalente; sib
es falso, fallará, produciendoa
más queb
.Ponga lo siguiente en la parte superior de su archivo:
Luego continúe con el código Python normal:
fuente
sys.version_info < (2, 7)
sys.version_info
tipo con una tupla?sys.version_info
solía ser una tupla; por ejemplo(2, 4, 6, 'final', 0)
; solo en Python 3 y 2.7 se cambió a un tipo separado, que sin embargo es comparable con las tuplas.Creo que la mejor manera es probar la funcionalidad en lugar de las versiones. En algunos casos, esto es trivial, no en otros.
p.ej:
Mientras sea lo suficientemente específico en el uso de los bloques try / except, puede cubrir la mayoría de sus bases.
fuente
Acabo de encontrar esta pregunta después de una búsqueda rápida mientras intentaba resolver el problema por mí mismo y se me ocurrió un híbrido basado en algunas de las sugerencias anteriores.
Me gusta la idea de DevPlayer de usar un script de contenedor, pero la desventaja es que terminas manteniendo múltiples contenedores para diferentes sistemas operativos, así que decidí escribir el contenedor en python, pero utilicé la misma lógica básica de "agarrar la versión ejecutando el exe" y se le ocurrió esto.
Creo que debería funcionar para 2.5 en adelante. Lo he probado en 2.66, 2.7.0 y 3.1.2 en Linux y 2.6.1 en OS X hasta ahora.
Sí, sé que la línea de decodificación / tira final es horrible, pero solo quería obtener rápidamente el número de versión. Voy a refinar eso.
Esto funciona bastante bien para mí por ahora, pero si alguien puede mejorarlo (o decirme por qué es una idea terrible), también sería genial.
fuente
Para los scripts de Python independientes , el siguiente truco de la cadena de documentación del módulo para aplicar una versión de Python (aquí v2.7.x) funciona (probado en * nix).
Esto también debería manejar el ejecutable faltante de Python, pero depende de grep. Ver aquí para el fondo.
fuente
Puedes consultar con
sys.hexversion
osys.version_info
.sys.hexversion
no es muy amigable para los humanos porque es un número hexadecimal.sys.version_info
es una tupla, por lo que es más amigable para los humanos.Verifique Python 3.6 o más reciente con
sys.hexversion
:Verifique Python 3.6 o más reciente con
sys.version_info
:sys.version_info
es más amigable para los humanos, pero toma más personajes. Lo recomendaríasys.hexversion
, aunque es menos amigable para los humanos.¡Espero que esto te ayude!
fuente
Estoy ampliando excelente respuesta de Akhan, que imprime un mensaje útil antes de la secuencia de comandos de Python es aún compilado.
Si desea asegurarse de que el script se ejecuta con Python 3.6 o posterior, agregue estas dos líneas en la parte superior del script de Python:
(Nota: la segunda línea comienza con cuatro comillas simples y termina con tres comillas simples. Esto puede parecer extraño, pero no es un error tipográfico).
La ventaja de esta solución es que el código como
print(f'Hello, {name}!')
no causará unaSyntaxError
si se usa una versión de Python anterior a 3.6. Verás este útil mensaje en su lugar:Por supuesto, esta solución solo funciona en shells similares a Unix, y solo cuando el script se invoca directamente (como
./script.py
:), y con los bits de permiso eXecute establecidos.fuente
Qué tal esto:
fuente
El problema es bastante simple. Usted verificó si la versión era menor que 2.4, no menor o igual que . Entonces, si la versión de Python es 2.4, no es menor que 2.4. Lo que deberías haber tenido fue:
no
fuente