2010-12-02 3 views
0

Если у меня есть модуль питона, который имеет кучу функций, скажет так:Can от <module> импорт * не работа иногда?

#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() 

Тогда я могу открыть питона и сделать следующее:

>>> 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 * line, я не нахожу foo в globals() от parser.py, когда он используется через funcs.py. Как такое могло произойти?

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

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

Вы должны рассмотреть возможность использования декоратора для перечисления функций, которые вам интересны. Это значительно упростит ваш код. – 2010-12-02 03:25:27

+0

@ Игнасио, как бы он это сделал? Я не вижу его – 2010-12-02 03:39:32

ответ

2

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
  • печати глобалов после импорта анализатор, чтобы увидеть, что он сделал
  • parser это встроенный модуль также. Обычно встроенный парсер должен загружать не ваши. Я бы сменил имя, чтобы у вас не было проблем.
  • Ваши импортирующие funcs, но парсер импортирует * из funcs?

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

0

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

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

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

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

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

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