Я столкнулся с проблемой импорта модулей в скрипт Python. Я сделаю все возможное, чтобы описать ошибку, почему я столкнулся с ней и почему я привязываю именно этот подход к решению моей проблемы (которую я опишу через секунду):
Предположим, у меня есть модуль, в котором я определил некоторые служебные функции / классы, которые относятся к сущностям, определенным в пространстве имен, в которое будет импортирован этот вспомогательный модуль (пусть «a» будет такой сущностью):
модуль1:
def f():
print a
И затем у меня есть основная программа, в которой определено "a", в которую я хочу импортировать эти утилиты:
import module1
a=3
module1.f()
Запуск программы вызовет следующую ошибку:
Traceback (most recent call last):
File "Z:\Python\main.py", line 10, in <module>
module1.f()
File "Z:\Python\module1.py", line 3, in f
print a
NameError: global name 'a' is not defined
Подобные вопросы задавались и раньше (два дня назад, дах), и было предложено несколько решений, однако я действительно не думаю, что они соответствуют моим требованиям. Вот мой конкретный контекст:
Я пытаюсь создать программу Python, которая подключается к серверу базы данных MySQL и отображает / изменяет данные с помощью графического интерфейса. Для чистоты я выделил кучу вспомогательных / служебных функций, связанных с MySQL, в отдельный файл. Однако все они имеют общую переменную, которую я изначально определил внутри модуля утилит, и которая является объектом курсора из модуля MySQLdb. Позже я понял, что объект курсора (который используется для связи с сервером db) должен быть определен в основном модуле, чтобы и основной модуль, и все, что в него импортируется, могли получить доступ к этому объекту.
Конечный результат будет примерно таким:
utilities_module.py:
def utility_1(args):
code which references a variable named "cur"
def utility_n(args):
etcetera
И мой основной модуль:
program.py:
import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
И затем, как только я пытаюсь вызвать любую из функций утилит, возникает вышеупомянутая ошибка «глобальное имя не определено».
В частности, предлагалось включить в файл утилит оператор "from program import cur", например:
utilities_module.py:
from program import cur
#rest of function definitions
program.py:
import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor() #cur is defined!
from utilities_module import *
Но это циклический импорт или что-то в этом роде, и, в конечном итоге, он тоже вылетает. Итак, мой вопрос:
Как, черт возьми, я могу сделать объект "cur", определенный в основном модуле, видимым для тех вспомогательных функций, которые в него импортированы?
Спасибо за ваше время и мои глубочайшие извинения, если решение было размещено в другом месте. Я просто не могу найти ответ сам, да и в моей книге больше нет трюков.
fetch_all
перебирать два списка. или просто так, что у вас может быть два разных потока / гринлета / цепочки обратных вызовов / что угодно, использующее базу данных без конфликтов).db
(иcur
, если вы настаиваете) в отдельный модуль, из которогоprogram
иutilities_module
импортировать его. Таким образом, вы не получите циклических зависимостей (импорт программы из модулей, которые программа импортирует) и путаницы, которая с ними связана.Ответы:
Глобальные переменные в Python являются глобальными для модуля , а не для всех модулей. (Многих это сбивает с толку, потому что, скажем, в C глобальное значение одинаково для всех файлов реализации, если вы явно не укажете его
static
.)Есть разные способы решить эту проблему в зависимости от вашего фактического использования.
Прежде чем даже пойти по этому пути, спросите себя, действительно ли это должно быть глобальным. Может быть, вам действительно нужен класс с
f
методом экземпляра, а не просто бесплатная функция? Тогда вы могли бы сделать что-то вроде этого:Если вам действительно нужен global, но он нужен только для использования
module1
, установите его в этом модуле.С другой стороны, если
a
он используется множеством модулей, поместите его в другое место и попросите всех импортировать его:… И в module1.py:
Не используйте
from
импорт, если переменная не должна быть константой.from shared_stuff import a
создаст новуюa
переменную, инициализированную для всего, чтоshared_stuff.a
упоминается во время импорта, и эта новаяa
переменная не будет затронута присваиваниямиshared_stuff.a
.Или, в редком случае, когда вам действительно нужно, чтобы он был действительно глобальным везде, например, встроенный, добавьте его во встроенный модуль. Точные детали отличаются между Python 2.x и 3.x. В 3.x это работает так:
источник
В качестве обходного пути вы можете рассмотреть возможность установки переменных среды на внешнем уровне, например, здесь.
main.py:
mymodule.py:
В качестве дополнительной меры предосторожности обработайте случай, когда MYVAL не определен внутри модуля.
источник
Функция использует глобальные переменные модуля, в котором она определена .
a = 3
Например, вместо настройки вы должны выполнять настройкуmodule1.a = 3
. Итак, если вы хотите, чтобы он былcur
доступен как глобальныйutilities_module
, установитеutilities_module.cur
.Лучшее решение: не используйте глобальные переменные. Передайте нужные вам переменные в функции, которые в них нуждаются, или создайте класс, чтобы связать все данные вместе и передать его при инициализации экземпляра.
источник
Этот пост - просто наблюдение за поведением Python, с которым я столкнулся. Возможно, советы, которые вы прочитали выше, не сработают для вас, если вы сделаете то же, что и я.
А именно, у меня есть модуль, который содержит глобальные / общие переменные (как было предложено выше):
Затем у меня был основной модуль, который импортирует общие материалы с помощью:
и некоторые другие модули, которые фактически заполняли эти массивы. Они вызываются основным модулем. При выходе из этих других модулей я ясно вижу, что массивы заполнены. Но при чтении их в основном модуле они были пустыми. Для меня это было довольно странно (ну, я новичок в Python). Однако, когда я меняю способ импорта sharedstuff.py в основной модуль, чтобы:
это сработало (массивы были заполнены).
Просто говорю'
источник
Самым простым решением этой конкретной проблемы было бы добавление другой функции в модуль, которая сохраняла бы курсор в переменной, глобальной для модуля. Тогда все остальные функции тоже смогут его использовать.
модуль1:
основная программа:
источник
Поскольку глобальные переменные зависят от модуля, вы можете добавить следующую функцию ко всем импортированным модулям, а затем использовать ее для:
Тогда все, что вам нужно передать текущим глобальным переменным, это:
источник
Поскольку я не видел этого в ответах выше, я подумал, что добавлю свой простой обходной путь, который заключается в
global_dict
том, чтобы просто добавить аргумент в функцию, требующую глобальных переменных вызывающего модуля, а затем передать dict в функцию при вызове; например:источник
ООП способ сделать это - сделать ваш модуль классом, а не набором несвязанных методов. Затем вы можете использовать
__init__
метод или метод установки, чтобы установить переменные вызывающего объекта для использования в методах модуля.источник