python - example - ¿Cómo lidiar con gracia con las importaciones de funciones futuras fallidas(__future__) debido a la versión anterior del intérprete?
python import from parent directory (3)
"Me gustaría informar al usuario que necesitan volver a ejecutar el programa con Python> = 2.6 y tal vez proporcionar algunas instrucciones sobre cómo hacerlo".
¿No es eso para lo que es un archivo README?
Aquí está tu alternativa. Una "envoltura": una pequeña mancha de Python que verifica el entorno antes de ejecutar su AOP objetivo.
Archivo: appwrapper.py
import sys
major, minor, micro, releaselevel, serial = sys.version_info
if (major,minor) <= (2,5):
# provide advice on getting version 2.6 or higher.
sys.exit(2)
import app
app.main()
Qué significa "importación directa". Puede examinar el contenido de __future__
. Todavía está obligado por el hecho de que a from __future__ import print_function
es información para el compilador, pero puede hurgar antes de importar el módulo que hace el trabajo real.
import __future__, sys
if hasattr(__future__, ''print_function''):
# Could also check sys.version_info >= __future__. print_function.optional
import app
app.main()
else:
print "instructions for upgrading"
¿Cómo maneja con gracia las importaciones de características futuras fallidas? Si un usuario se está ejecutando con Python 2.5 y la primera declaración en mi módulo es:
from __future__ import print_function
La compilación de este módulo para Python 2.5 fallará con un:
File "__init__.py", line 1
from __future__ import print_function
SyntaxError: future feature print_function is not defined
Me gustaría informar al usuario que necesitan volver a ejecutar el programa con Python> = 2.6 y tal vez proporcionar algunas instrucciones sobre cómo hacerlo. Sin embargo, para citar PEP 236 :
Las únicas líneas que pueden aparecer antes de una future_statement son:
- El módulo docstring (si lo hay).
- Comentarios.
- Líneas en blanco.
- Otros future_statements.
Entonces no puedo hacer algo como:
import __future__
if hasattr(__future__, ''print_function''):
from __future__ import print_function
else:
raise ImportError(''Python >= 2.6 is required'')
Porque cede:
File "__init__.py", line 4
from __future__ import print_function
SyntaxError: from __future__ imports must occur at the beginning of the file
Este fragmento del PEP parece dar la esperanza de hacerlo en línea:
P: Quiero ajustar future_statements en try / except blocks, para poder usar código diferente dependiendo de qué versión de Python estoy ejecutando. ¿Por qué no puedo?
A: ¡Lo siento! try / except es una característica de tiempo de ejecución; future_statements son principalmente trucos en tiempo de compilación, y tu try / except ocurre mucho después de que el compilador haya terminado. Es decir, cuando intenta / exceptúa, la semántica vigente para el módulo ya está lista. Dado que try / except no lograría lo que parece que debería lograr, simplemente no está permitido. También queremos que estas declaraciones especiales sean muy fáciles de encontrar y de reconocer.
Tenga en cuenta que puede importar __future__ directamente, y usar la información que contiene, junto con sys.version_info, para averiguar dónde se encuentra el lanzamiento que está ejecutando en relación con el estado de una función determinada.
Ideas?
Simplemente ponga un comentario en la misma línea con la "from __future__ import ..."
, como esta:
from __future__ import print_function, division # We require Python 2.6 or later
Como Python muestra la línea que contiene el error, si intenta ejecutar el módulo con Python 2.5 obtendrá un buen error descriptivo:
from __future__ import print_function, division # We require Python 2.6 or later
SyntaxError: future feature print_function is not defined
Un método bastante hacky pero simple que he usado antes es explotar el hecho de que los literales de bytes se introdujeron en Python 2.6 y usan algo así cerca del inicio del archivo:
b''This module needs Python 2.6 or later. Please do xxx.''
Esto es inofensivo en Python 2.6 o posterior, pero un SyntaxError
en cualquier versión anterior. Cualquier persona que intente compilar su archivo recibirá un error, pero también recibirá el mensaje que quiera.
Puede pensar que como tendrá que tener esta línea después de su from __future__ import print_function
entonces será la importación la que generará SyntaxError
y no podrá ver el útil mensaje de error, pero curiosamente el último error tiene prioridad. Sospecho que como el error de la importación no es realmente un error de sintaxis en sí mismo, no se genera en el primer pase de compilación, por lo que los errores de sintaxis reales aparecen primero (pero supongo).
Esto puede no cumplir con los criterios para ser ''elegante'', y es muy específico de Python 2.6, pero es rápido y fácil de hacer.