Может из <module>import * иногда не работать? - PullRequest
0 голосов
/ 02 декабря 2010

Если у меня есть модуль Python, который имеет несколько функций, скажем так:

#funcs.py
def foo() :
    print "foo!"

def bar() :
    print "bar!"

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

#parser.py
from funcs import *

def execute(command):
    command = command.split()
    for c in command:
        function = globals()[c]
        function()

Затем я могу открыть python и сделать следующее:

>>> import parser
>>> parser.execute("foo bar bar foo")
foo!
bar!
bar!
foo!

Я хочу добавить вспомогательную функцию к funcs.py, которая позволяет вызывать список функцийкак сама функция:

#funcs.py (new version)
import parser

def foo() :
    print "foo!"

def bar() :
    print "bar!"

def parse(commands="foo foo") :
    parser.execute(commands)

Теперь я могу рекурсивно анализировать из самого анализатора:

>>> import parser
>>> parser.execute("parse")
foo!
foo!
>>> parser.execute("parse bar parse")
foo!
foo!
bar!
foo!
foo!

Но по какой-то причине я не могу просто запустить parse из funcs, как я получаю ключевую ошибку:

>>> import funcs
>>> funcs.parse("foo bar")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "funcs.py", line 11, in parse
    parser.execute(commands)
  File "parser.py", line 6, in execute
    function = globals()[c]
KeyError: 'foo'

Так что, хотя foo следует импортировать в parser.py через строку from funcs import *, я не нахожу foo в globals()parser.py при использовании через funcs.py.Как это могло произойти?

Наконец, я должен указать, что импорт parser, а затем funcs (но только в этом порядке) позволяет ему работать должным образом:

>>> import parser
>>> import funcs
>>> funcs.parse("foo bar")
foo!
bar!

Ответы [ 3 ]

2 голосов
/ 02 декабря 2010

import module_name делает что-то принципиально отличное от того, что делает from module_name import *.

Первый создает глобальное имя module_name, которое имеет тип module и которое содержит имена модулей, доступ к которым осуществляется как атрибуты. Последний создает глобальный для каждого из этих имен в module_name, но не для самого module_name.

Таким образом, когда вы import funcs, foo и bar не помещены в globals() и, следовательно, не найдены, когда execute ищет их.

Подобные циклические зависимости (при попытке parser импортировать имена из funcs, в то время как funcs также импортирует parser) плохие. Явное лучше, чем неявное. Не пытайтесь творить столько магии. Сообщите parse(), какие функции доступны.

0 голосов
/ 02 декабря 2010

Ваш "парсер" - довольно плохая идея.

Сделайте это вместо этого.

def execute(*functions):
    for function in functions:
        function()

Затем вы можете открыть Python и сделать следующее:

>>> import parser
>>> from funcs import foo, bar 
>>> parser.execute(foo, bar, bar, foo)

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

0 голосов
/ 02 декабря 2010
  • Распечатайте глобальные переменные после импорта парсера, чтобы увидеть, что он сделал
  • parser это также встроенный модуль.Обычно встроенный парсер должен загружать не ваш.Я бы поменял имя, чтобы у вас не было проблем.
  • Вы импортируете funcs, но парсер импортирует * из funcs?

Я бы тщательно подумал о том, в каком порядке вы импортируете модули и гдеони вам нужны.

...