2015-01-03 2 views
1

Можно ли вызвать глобальную функцию из импортируемой функции в Python 3?Python: как вызвать глобальную функцию из импортированного модуля

./folders/folder1/def.py

def do_test(): 
    print("++ def.do_test()") 
    global_function_1() 
    print("-- def.do_test()") 

./main.py

import importlib 

def global_function_1(): 
    print("doing function 1 thing...") 

mod = importlib.import_module('folders.folder1.def') 
mod.do_test() 

У меня есть ошибка, как это.

++ def.do_test() 
Traceback (most recent call last): 
    File "C:\src\python\class2\main.py", line 10, in <module> 
    mod.do_test() 
    File "C:\src\python\class2\folders\folder1\def.py", line 4, in do_test 
    global_function_1() 
NameError: name 'global_function_1' is not defined 

По-видимому, те же функции работают нормально, если они определены в одном файле.

def global_function_1(): 
    print("calling the global function 1") 


def do_test(): 
    print("++ def.do_test()") 
    global_function_1() 
    print("-- def.do_test()") 

do_test() 

Результаты является

++ def.do_test() 
calling the global function 1 
-- def.do_test() 

Если Python не позволяет этого, что бы ближайшую альтернативу? В моем реальном проекте глобальные функции имеют число обращений к глобальным переменным . Если все возможное, я бы хотел избежать размещения всех глобальных функций и переменных в отдельном классе.

EDIT: Вышеприведенный фрагмент кода, чтобы выделить мою проблему. В моем реальном проекте,

  1. У меня есть дюжина глобальных функций. Таким образом, передача указателя через параметр функции не рекомендуется.
  2. У меня есть десяток других файлов def.py в нескольких папках. Мне нужно забрать файл def.py во время выполнения в зависимости от условий сорта. Таким образом, статическая ссылка с main.py на def.py не рекомендуется.
+0

Что-нибудь случилось с добавлением 'от главного импорта global_function_1' в' def.py'? –

+0

В вашем вопросе нет классов в коде, так как все это относится к «из класса» в названии вашего вопроса? – martineau

+0

@Rawing - Спасибо за советы. Я привел свой результат в ответ SmeltQuake ниже, который дал мне тот же совет. – Tony

ответ

1

я смог main.py работать со следующей настройкой.

(Обратите внимание, я должен был добавить пустые __init__.py файлов в обоих folders и folder1 подкаталогов, чтобы получить импорт работать.)

Файл .\class2\folders\folder1\def.py

from main import global_function_1 

def do_test(): 
    print("++ def.do_test()") 
    global_function_1() 
    print("-- def.do_test()") 

Файл .\class2\main.py

import importlib 

def global_function_1(): 
    print("doing function 1 thing...") 

if __name__ == '__main__': 
    mod = importlib.import_module('folders.folder1.def') 
    mod.do_test() 

Выход:

++ def.do_test() 
doing function 1 thing... 
-- def.do_test() 
+0

Спасибо! Да, это работает в моем Кроме того, я обнаружил, что «если __name__ == '__main__':" также необходимо заставить его работать в дополнение к пустым файлам __init__.py. – Tony

+1

Да, это необычная ситуация, 'main.py' импортирует что-то, что импортирует его - вот почему нужен 'if __name__ == '__main __':'. Я удивлен, хотя что он не входит в бесконечный цикл импорта без него ... – martineau

0

Что вы создали, называется модулем. Его нельзя использовать, если он не импортируется в файл, в котором он используется. В вашем случае def.py необходимо импортировать main.

Импорт можно сделать так:

from moduleFilename import moduleFunctionname 

вы можете сделать

moduleFunctionname() 

Альтернатива:

import moduleFilename 
moduleFilename.moduleFunctionname() 

EDIT: Похоже, Rawing был быстрее с его комментарием .. .

+0

Я попробовал, но привел к другому сбою. Файл «C: \ src \ python \ class2 \ folders \ folder1 \ def.py», строка 1, в import main Файл «C: \ src \ python \ class2 \ main.py», строка 8, в mod.do_test() AttributeError: объект 'module' не имеет атрибута 'do_test' – Tony

+0

Не могли бы вы опубликовать обновленный код? Вероятно, вы либо импортировали его в неправильный файл, либо ошиблись, но я не уверен. – SmeltQuake

+0

Подождите, я думаю, я могу понять, что вы имели в виду. Удалите первую и последнюю две строки кода из main.py, который вы опубликовали, я думаю, что importlib не подходит к тому, что вы хотите сделать. Затем добавьте «import main» в def.py и получите доступ к своим функциям, введя «main. () в def.py. Вот документы на тему: https://docs.python.org/2/ tutorial/modules.html – SmeltQuake

0

Если вы хотите сохранить folders.folder1.def независимо от задней импортирующих вещи, как это похоже на то, как библиотека или плагин или таким образом, вы можете прибегнуть к получению его в качестве обратного вызова:

библиотека:

def do_test(callback): 
    print("++ def.do_test()") 
    callback() 
    print("-- def.do_test()") 

основной модуль:

import importlib 

def global_function_1(): 
    print("doing function 1 thing...") 

mod = importlib.import_module('folders.folder1.def') 
mod.do_test(global_function_1) 
+0

Спасибо за ввод. Да, это работает. Но это не масштабируется, когда у меня есть дюжина глобальной функции в моем реальном проекте. – Tony

Смежные вопросы