У меня есть небольшая проблема с импортом, из-за которой создаются переменные со ссылками на объекты, отличные от ожидаемых, и все зависит от того, импортируется ли модуль, который я пишу, «как есть» или как часть пакета.
Допустим, у меня есть простой модуль, который определяет класс Config
и функцию для его настройки:
class Config:
def __init__(self, **kwargs):
if kwargs.get("print_keys", None):
self.print_keys = kwargs.pop("print_keys")
else:
self.print_keys = ["centre", "shortName"]
rcParams = Config()
def set_config(config=None):
global rcParams
print("Before change:", id(rcParams))
if config is None:
config = Config()
rcParams = config
print("After change:", id(rcParams))
Если я сохраню это в модуле с именем simple.py
, то смогу успешно протестировать это с помощью этого модуля:
# import gribtool as gt # note this line is uncommented later
import simple as gt # note this line is commented later
def test_set_config():
config = gt.Config(print_keys=["centre"])
print("Initial rcParams id:", id(gt.rcParams))
gt.set_config(config=config)
print("Updated rcParams id:", id(gt.rcParams))
assert gt.rcParams.print_keys == ["centre"]
test_set_config()
Результат:
Initial rcParams id: 128205347716160
Before change: 128205347716160
After change: 128205347716832
Updated rcParams id: 128205347716832
Все идет нормально. Проблема в том, что я хочу, чтобы это было частью пакета. Я скопировал (фактически связал) этот модуль в пакет (каталог) с именем gribtool
, а затем создал файл __init__.py
с ожидаемым содержимым:
from .simple import *
Содержимое каталога такое:
├── gribtool
│ ├── __init__.py
│ └── simple.py -> ../simple.py
├── simply.py
└── test.py
Затем я раскомментирую строку с import gribtool as gt
в тестовом модуле выше, и затем происходит сбой с таким выводом:
Initial rcParams id: 134251413862864
Before change: 134251413862864
After change: 134251413864064
Updated rcParams id: 134251413862864
Traceback (most recent call last):
File "/home/navarro/AEMET/GRIB_TOOL/test_config.py", line 13, in <module>
test_set_config()
File "/home/navarro/AEMET/GRIB_TOOL/test_config.py", line 10, in test_set_config
assert gt.rcParams.print_keys == ["centre"]
AssertionError
Как видите, проблема в том, что rcParams
, который модифицируется внутри функции set_config
, отличается от модуля simple
, несмотря на инструкцию global
.
Как мне убедиться, что я ссылаюсь на правильные объекты?
Просто измените свой код на этот (test.py
):
from gribtool import simple
def test_set_config():
config = simple.Config(print_keys=["centre"])
print("Initial rcParams id:", id(simple.rcParams))
simple.set_config(config=config)
print("Updated rcParams id:", id(simple.rcParams))
assert simple.rcParams.print_keys == ["centre"]
test_set_config()
Это поможет. Я не знаю, почему изменяется значение объекта, но я знаю, что ваш исходный оператор import
не будет работать. Просто импортируйте соответствующий модуль напрямую и используйте форму module.object
для доступа к нужному объекту.