Я нашел грязный способ сделать то же самое, отфильтровывая по версии выпуска по: ]
Я не знаю, как фильтровать по номеру версии.
Есть идеи?
Это было действительно хорошее обсуждение этого вопроса на comp.lang.python в прошлом году. Он довольно подробно отвечает на ваш вопрос.
Импорт действительно довольно прост. Просто помните следующее:
'import' и 'from xxx import yyy' являются исполняемыми операторами. Они выполняют когда запущенная программа достигает этой строки.
Если модуль отсутствует в sys.modules, то при импорте создается новый модуль. запись в sys.modules, а затем выполняет код в модуле. Это не вернуть управление вызывающему модулю до завершения выполнения.
Если модуль существует в sys.modules, то импорт просто возвращает это модуль, завершил ли он выполнение или нет. Вот почему циклический импорт может возвращать модули, которые кажутся частично пустыми.
Наконец, исполняемый скрипт запускается в модуле с именем __main__, импортируя скрипт под своим именем создаст новый модуль, не связанный с __main __.
Возьмите эту партию вместе, и вы не должны получать никаких сюрпризов при импорте модули.
Если вы выполните import foo
внутри bar
и import bar
внутри foo
, все будет работать нормально. К тому времени, когда что-нибудь действительно запустится, оба модуля будут полностью загружены и будут иметь ссылки друг на друга.
Проблема в том, что вместо этого вы делаете из foo import abc
и из bar import xyz
. Потому что теперь каждый модуль требует, чтобы другой модуль уже был импортирован (чтобы импортируемое имя существовало), прежде чем его можно будет импортировать.
Проблема в том, что вместо этого вы делаете из foo import abc
и из bar import xyz
. Потому что теперь каждый модуль требует, чтобы другой модуль уже был импортирован (чтобы импортируемое имя существовало), прежде чем его можно будет импортировать.
Проблема в том, что вместо этого вы делаете из foo import abc
и из bar import xyz
. Потому что теперь каждый модуль требует, чтобы другой модуль уже был импортирован (чтобы импортируемое имя существовало), прежде чем его можно будет импортировать.
Циклический импорт завершается, но нужно соблюдать осторожность, чтобы не использовать циклически импортированные модули во время инициализации модуля.
Рассмотрим следующие файлы:
a.py :
print "a in"
import sys
print "b imported: %s" % ("b" in sys.modules, )
import b
print "a out"
b.py:
print "b in"
import a
print "b out"
x = 3
Если вы выполните a.py, вы получите следующее:
$ python a.py
a in
b imported: False
b in
a in
b imported: True
a out
b out
a out
При втором импорте b.py (во втором a в
), интерпретатор Python больше не импортирует b
, поскольку он уже существует в модуле dict.
Если вы попытаетесь получить доступ к bx
из a
во время инициализации модуля , вы получите AttributeError
.
Добавьте следующую строку в a.py
:
print b.x
Затем выведите:
У меня есть пример, который меня поразил!
foo.py
import bar
class gX(object):
g = 10
bar.py
from foo import gX
o = gX()
main.py
import foo
import bar
print "all done"
В командной строке: $ python main.py
Traceback (most recent call last):
File "m.py", line 1, in <module>
import foo
File "/home/xolve/foo.py", line 1, in <module>
import bar
File "/home/xolve/bar.py", line 1, in <module>
from foo import gX
ImportError: cannot import name gX
Существует много больших ответов здесь. В то время как существуют обычно быстрые решения проблемы, некоторые из которых чувствуют больше pythonic, чем другие, если у Вас есть роскошь выполнения некоторого рефакторинга, другой подход должен проанализировать организацию Вашего кода и попытаться удалить круговую зависимость. Можно найти, например, что Вы имеете:
файл a.py
from b import B
class A:
@staticmethod
def save_result(result):
print('save the result')
@staticmethod
def do_something_a_ish(param):
A.save_result(A.use_param_like_a_would(param))
@staticmethod
def do_something_related_to_b(param):
B.do_something_b_ish(param)
B.py
from a import A
class B:
@staticmethod
def do_something_b_ish(param):
A.save_result(B.use_param_like_b_would(param))
Файла В этом случае, просто переместив один статический метод для отдельного файла, говорят c.py
:
файл c.py
def save_result(result):
print('save the result')
позволит удалять save_result
метод от A и таким образом позволит удалять импорт от в b:
Пересмотренный файл a.py
from b import B
from c import save_result
class A:
@staticmethod
def do_something_a_ish(param):
A.save_result(A.use_param_like_a_would(param))
@staticmethod
def do_something_related_to_b(param):
B.do_something_b_ish(param)
Пересмотренный файл b.py
from c import save_result
class B:
@staticmethod
def do_something_b_ish(param):
save_result(B.use_param_like_b_would(param))
, Таким образом, если у Вас есть инструмент (например, pylint или PyCharm), который сообщает относительно методов, которые могут быть статическими, просто бросив staticmethod
, декоратор на них не мог бы быть лучшим способом заставить предупреждение замолчать. Даже при том, что метод кажется связанным с классом, могло бы быть лучше выделить его, особенно если у Вас есть несколько тесно связанных модулей, которым, возможно, понадобилась бы та же функциональность, и Вы намереваетесь практиковать принципы DRY.