Как изящно справиться с неудачными импортом будущих функций (__future__) из-за старой версии интерпретатора? - PullRequest
68 голосов
/ 23 декабря 2008

Как вы изящно справляетесь с неудачным импортом в будущем? Если пользователь работает с 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 :

Единственные строки, которые могут появиться раньше Будущее:

  • Строка документации модуля (если есть).
  • Комментарии.
  • Пустые строки.
  • Другие записи о будущем.

Так что я не могу сделать что-то вроде:

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, похоже, дает надежду сделать это встроенным:

Q: я хочу обернуть future_statements в try / кроме блоков, так что я могу использовать другой код в зависимости от того, какой версия Python у меня запущена. Зачем я не могу?

A: Извините! попробуйте / кроме времени выполнения особенность; будущие_отношения прежде всего трюки во время компиляции, и Ваша попытка / кроме происходит через много времени после компилятор готов. То есть раз вы пробуете / кроме семантики в действительности для модуля уже сделка сделана Так как попробуй / кроме не смог бы сделать то, что он выглядит как это должно быть достигнуто, это просто не положено. Мы также хотим сохранить эти специальные заявления очень легко найти и распознать.

Обратите внимание, что вы можете импортировать __future__ и использовать информацию в это, наряду с sys.version_info, чтобы выяснить, где релиз вы работает под трибунами по отношению к статус данной функции.

Идеи

Ответы [ 3 ]

58 голосов
/ 23 декабря 2008

"Я хотел бы сообщить пользователю, что ему нужно перезапустить программу с Python> = 2.6, и, возможно, предоставить некоторые инструкции о том, как это сделать."

Разве не для этого нужен файл README?

Вот ваша альтернатива. «Обертка»: маленький кусочек Python, который проверяет среду перед запуском вашей целевой системы.

Файл: 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__. Вы все еще связаны тем фактом, что a 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"
46 голосов
/ 14 июня 2010

Довольно хакерский, но простой метод, который я использовал ранее, состоит в том, чтобы использовать тот факт, что байтовые литералы были введены в 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, но это быстро и легко сделать.

40 голосов
/ 31 августа 2011

Просто поместите комментарий в той же строке с "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
...