/ / Importovacia premenná priamo poskytuje inú hodnotu ako importovanie modulu v Pythone - python, python-import

Importovanie premennej priamo prináša inú hodnotu ako importovanie jej modulu v Python-python, python-import

Mám tri moduly:

  • constants, ktorá obsahuje načítanú konfiguráciu a ďalšie veci v triede
  • main, ktorý sa inicializuje constants keď je spustený
  • user, ktorý dováža constants a pristupuje k svojej konfigurácii.

constants modul (zjednodušený) vyzerá takto:

class Constants:
def __init__(self, filename):
# Read values from INI file
config = self.read_inifile(filename)
self.somevalue = config["ex"]["ex"]

def read_inifile(self, filename):
# reads inifile

constants: Constants = None

def populate_constants(filename):
global constants
constants = Constants(filename)

Jednoduchý objekt, ktorý by mal obsahovať konfiguráciu, nič priekopnícke.

Funkcia populate_constants() je povolaný od main pri štarte programu.

Teraz sa stane divnosť - keď importujem constants modul od user ako je tento, constants je None:

from toplevelpkg.constants import constants
print(constants)

None

Ak to však importujem, constants je inicializovaný podľa očakávania:

from toplevelpkg import constants
print(constants.constants)

<trumpet.constants.Constants object at 0x035AA130>

Prečo to je?

EDIT: v mojom kóde funkcia, ktorá sa pokúša čítať constants je spustený asynchrónne prostredníctvom await loop.run_in_executor(None, method_needing_import), Nie ste si istí, či to môže spôsobiť problémy?

(a ako vedľajšia otázka, je dobré mať objekt na udržiavanie konfigurácie, ktorý analyzuje konfiguračný súbor a poskytuje ho ako svoje členské premenné?)

odpovede:

2 pre odpoveď č. 1

Medzi nimi je skutočne rozdiel

from mymodule import obj
(...)
do_something_with(obj)

a

import mymodule
(...)
do_something_with(mymodule.obj)

V prvom prípade sa správa takto:

 import mymodule
obj = mymodule.obj
del mymodule

čo znamená, že v tomto bode v súčasnom module obj je „globálny“ (čo v Pythone v skutočnosti znamená „modul-úroveň“, nie „široká aplikácia“) názov viazaný na čokoľvek mymodule.obj bol kedy bol importovaný (vo vašom prípade: None). Od tej doby, mymodule.obj a modul-local obj Mená žijú v rôznych menných priestoroch (prvé v mymodule namespace, druhý v aktuálnom mennom priestore modulu) a rebinding mymodule.obj odkiaľkoľvek nezmení nič na to, čo má súčasný modul obj je viazaný na. V skutočnosti je to presne také, ako keby ste to robili:

a = 2
b = a
a = 4

Po treťom vyhlásení b je samozrejme stále povinný 2 - rebounding a na 4 nemá vplyv b.

V druhom prípade (import mymodule) to, čo je spojené s menným priestorom importujúceho modulu, je celok mymodule objekt, takže ak mymodule.obj sa odrazí (zvnútra) mymodule alebo kdekoľvek inde) zmena bude viditeľná v importujúcom module. V tomto prípade je to ekvivalentné

a = {"x": 2}
b = a
a["x"] = 4

V takom prípade bude zmena viditeľná od b["x"] od tej doby a a b sú stále viazané na ten istý objekt.

wrt / vaša vedľajšia otázka: áno, mať nejaký „konfiguračný“ objekt je celkom bežný model. Možno sa budete chcieť uistiť, že ho môžete zostaviť aj „od nuly“ (myslím, nie nevyhnutne z konfiguračného súboru), aby sa zjednodušilo testovanie jednotiek.