Как изящно справиться с неудачным будущим импортом функций (future) из-за старой версии интерпретатора?
как вы изящно справляетесь с неудачным будущим импортом функций? Если пользователь работает с использованием Python 2.5 и первый оператор в моем модуле:
from __future__ import print_function
компиляция этого модуля для Python 2.5 завершится с ошибкой:
File "__init__.py", line 1
from __future__ import print_function
SyntaxError: future feature print_function is not defined
Я хотел бы сообщить пользователю, что им нужно перезапустить программу с Python >= 2.6 и, возможно, предоставить некоторые инструкции о том, как это сделать. Однако, чтобы процитировать PEP 236:
только линии, которые могут появляются раньше
в future_statement являются:
- модуль docstring (если есть).
- комментарии.
- пустые строки.
- другие future_statements.
так что я не могу сделать что-то вроде:
import __future__
if hasattr(__future__, 'print_function'):
from __future__ import print_function
else:
raise ImportError('Python >= 2.6 is required')
потому что это дает:
File "__init__.py", line 4
from __future__ import print_function
SyntaxError: from __future__ imports must occur at the beginning of the file
этот фрагмент из PEP, кажется, дает надежду сделать это inline:
Q: я хочу обернуть future_statements
в блоки try и except, так что я могу использовать
различный код в зависимости от которого
версия Python, которую я запускаю. Почему
разве я не могу?
A: Извините! try / except-это среда выполнения
особенность; future_statements являются
в первую очередь трюки времени компиляции, и
ваша попытка / исключение происходит долго после
компилятор готов. То есть, по
время, когда вы пытаетесь / кроме того, семантика
в действительности для данного модуля уже
договорились. С try и except
не сделал бы то, что он выглядит
как это должно быть сделано, это просто
не позволять. Мы также хотим сохранить
эти специальные заявления очень легко
найти и распознать.
обратите внимание, что вы можете импорт __будущее__
сразу, и используйте информацию внутри
это, вместе с sys.version_info, чтобы
выясните, где релиз вы находитесь
под выступает по отношению к
учитывая статус функции.
идеи?
3 ответов:
" Я хотел бы сообщить пользователю, что им нужно перезапустить программу с Python >= 2.6 и, возможно, предоставить некоторые инструкции о том, как это сделать."
разве не для этого нужен файл README?
вот ваш вариант. "Оболочка": небольшой blob Python, который проверяет среду перед запуском вашего целевого aop.
файл: 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()
что означает "прямой импорт". Вы можете изучить содержимое
__future__. Ты еще связано то, чтоfrom __future__ import print_functionэто информация для компилятора, но вы можете покопаться перед импортом модуля, который делает реальную работу.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"
довольно хаки, но простой метод, который я использовал раньше, заключается в том, чтобы использовать тот факт, что байтовые литералы были введены в Python 2.6 и использовать что-то вроде этого в начале файла:
b'This module needs Python 2.6 or later. Please do xxx.'это безвредно в Python 2.6 или более поздней, но
SyntaxErrorв любых более ранних версиях. Любой, кто пытается скомпилировать ваш файл, все равно получит ошибку, но они также получат любое сообщение, которое вы хотите дать.можно подумать, что вы будете иметь эту строку после
from __future__ import print_functionтогда это будет импорт, который генерируетSyntaxErrorи вы не увидите полезное сообщение об ошибке, но, как ни странно, более поздняя ошибка имеет приоритет. Я подозреваю, что поскольку ошибка от импорта на самом деле не является синтаксической ошибкой сама по себе, она не возникает на первом этапе компиляции, и поэтому сначала возникают реальные синтаксические ошибки (но я предполагаю).это может не соответствовать вашим критериям для того, чтобы быть "изящным", и это очень специфично для Python 2.6, но это быстро и легко делать.
просто поместите комментарий в ту же строку с
"from __future__ import ...", например:from __future__ import print_function, division # We require Python 2.6 or laterпоскольку Python отображает строку, содержащую ошибку, если вы попытаетесь запустить модуль с Python 2.5, вы получите хорошую описательную ошибку:
from __future__ import print_function, division # We require Python 2.6 or later SyntaxError: future feature print_function is not defined
Comments