Подтвердить что ты не робот

Как мы можем сделать импорт __future__ глобальным?

Характеристики: Python 2.7

Я работаю над проектом с несколькими модулями, я хочу активировать некоторые функции из модуля __future__ во всех них. Я хотел бы импортировать все функции, которые мне нужны на одном модуле, а затем импортировать этот единственный модуль для всех остальных, и эти функции будут активны во всех них или что-то в этом роде.

Я пробовал:

[A.py]

from __future__ import division

[B.py]

import A
print(1/2)

Запуск B.py деление по-прежнему целое. Я пробовал:

[A.py]

print(1/2)

[B.py]

from __future__ import division
import A

Запуск B.py дал тот же результат. В обоих предыдущих примерах я также попытался переключить 'import A' на 'from A import *' с теми же результатами.

Я искал Google некоторое время и нашел лучшее описание о том, как модуль __future__ работает, очевидно, в документации Python. Там я мог только найти уверенность, что функции будут активны в модуле, в который они были импортированы, без каких-либо упоминаний о том, как сделать это глобально.

Итак, я хотел бы знать, есть ли способ сделать это, как описанный мной, или создать какой-то файл конфигурации времени выполнения, или с помощью некоторых других средств.

4b9b3361

Ответ 1

Невозможно сделать это на языке; вы действительно не можете сделать __future__ импорт глобальным в этом смысле. (Ну, вы, вероятно, можете заменить нормальные операторы import чем-то сложным вокруг imp или что-то в этом роде. См. Документацию Future statement и прокрутите вниз к "Коду, составленному..." Но ничего подобного почти наверняка - плохая идея.)

Причина в том, что from __future__ import division на самом деле не является нормальным импортом. Или, скорее, это больше, чем обычный импорт. Фактически вы получаете имя под названием division, которое вы можете проверить, но просто отсутствие этого значения не имеет эффекта, поэтому передача его другим модулям не влияет на эти модули. Помимо обычного импорта, у Python есть специальная магия, которая обнаруживает импорт __future__ в верхней части модуля или в интерактивном интерпретаторе и изменяет способ компиляции вашего кода. См. будущее для части "реального импорта" и Будущие утверждения для "волшебной" части, если вы хотите получить все детали.

И нет файла конфигурации, который позволяет это сделать. Но есть параметр командной строки:

python -Qnew main.py

Это имеет тот же эффект, что и при использовании from __future__ import division.

Вы можете добавить это в строки #! или alias pyfuturediv='python -Qnew' (или даже alias python='python -Qnew') в своей оболочке или что-то еще, что, возможно, так же хорошо, как файл конфигурации для ваших целей.

Но на самом деле, если вы хотите убедиться, что модуль B получает деление нового стиля, вы, вероятно, должны иметь объявление __future__ в B. В первую очередь.

Или, конечно, вы могли бы просто написать для Python 3.0+ вместо 2.3-2.7. (Обратите внимание, что некоторые из основных разработчиков были против наличия аргументов командной строки, потому что "правильный способ получить функцию X во всем мире - использовать версию Python >= функция X MandatoryRelease".) Или используйте //, если вы имеете в виду //.

Другая возможность - использовать six, модуль, разработанный, чтобы позволить вам писать код, который почти Python 3.3, и работать с ним в 2.4 -2,7 (и 3,0-3,2). Например, вы не получаете функцию print, но получаете функцию print_, которая работает точно так же. Вы не получаете литералы из Юникода, но вы получаете u() поддельные литералы, которые, вместе с объявлением кодировки UTF-8 в источнике, почти достаточно хороши. И он предоставляет множество вещей, которые вы также не можете получить от __future__ - StringIO и BytesIO, exec как функция, функция next и т.д.

Если проблема в том, что у вас есть 1000 исходных файлов, и вам больно их редактировать, вы можете использовать sed или использовать 3to2 только с опцией, которая фиксирует деление или...

Ответ 2

Другим подходом будет использование isort. isort имеет флаг командной строки -a, чтобы добавить импорт в файлы, которые вы указали. Простое выполнение isort без аргументов будет рекурсивно выполнять все файлы python в текущем рабочем каталоге и во всех подкаталогах.

Если, как и я, у вас есть виртуальная среда внутри этой папки, и вы используете git (или имеете эквивалентный способ перечисления только ваших файлов) и не хотите запускать его во всех файлах внутри этой виртуальной среды, вы можете использовать что-то вроде:

git ls-tree -r HEAD --name-only | grep "\.py$" | xargs isort -a -y "from __future__ import division"