Zanurkuj w Pythonie/Korzystanie z sys.modules
Wygląd
Korzystanie z sys.modules
[edytuj]Moduły, podobnie jak wszystko inne w Pythonie, są obiektami. Jeśli wcześniej zaimportowaliśmy pewien moduł, możemy pobrać do niego referencję za pośrednictwem globalnego słownika sys.modules.
Przykład. Wprowadzenie do
sys.modules
>>> import sys #(1)
>>> print '\n'.join(sys.modules.keys()) #(2)
win32api
os.path
os
exceptions
__main__
ntpath
nt
sys
__builtin__
site
signal
UserDict
stat
- Moduł
syszawiera informacje dotyczące systemu jak np. wersję uruchomionego Pythona (sys.versionlubsys.version_info) i opcje dotyczące systemu np. maksymalna dozwolona głębokość rekurencji (sys.getrecursionlimit()isys.setrecursionlimit()). sys.modulesjest słownikiem zawierającym wszystkie moduły, które zostały zaimportowane od czasu startu Pythona. W słowniku tym kluczem jest nazwa danego modułu, a wartością jest obiekt tego modułu. Dodajmy, że jest tu więcej modułów niż nasz program zaimportował. Python wczytuje niektóre moduły podczas startu, a jeśli używasz IDE Pythona ,sys.moduleszawiera wszystkie moduły zaimportowane przez wszystkie programy uruchomione wewnątrz IDE.
Poniższy przykład pokazuje, jak wykorzystywać sys.modules.
Przykład. Korzystanie z
sys.modules
>>> import fileinfo #(1) >>> print '\n'.join(sys.modules.keys()) win32api os.path os fileinfo exceptions __main__ ntpath nt sys __builtin__ site signal UserDict stat >>> fileinfo <module 'fileinfo' from 'fileinfo.pyc'> >>> sys.modules["fileinfo"] #(2) <module 'fileinfo' from 'fileinfo.pyc'>
- Podczas importowania nowych modułów, zostają one dodane do
sys.modules. To tłumaczy dlaczego ponowne zaimportowanie tego samego modułu jest bardzo szybkie. Otóż Python aktualnie posiada wczytany i zapamiętany moduł wsys.modules, więc za drugim razem kiedy importujemy moduł, Python spogląda po prostu tylko do tego słownika. - Podając nazwę wcześniej zaimportowanego modułu (w postaci łańcucha znaków), możemy pobrać referencję do samego modułu poprzez bezpośrednie wykorzystanie słownika
sys.modules.
Kolejny przykład pokazuje, jak wykorzystywać atrybut klasy __module__ razem ze słownikiem sys.modules, aby pobrać referencję do modułu, w którym ta klasa jest zdefiniowana.
Przykład. Atrybut klasy
__module__
>>> from fileinfo import MP3FileInfo >>> MP3FileInfo.__module__ #(1) 'fileinfo' >>> sys.modules[MP3FileInfo.__module__] #(2) <module 'fileinfo' from 'fileinfo.pyc'>
- Każda klasa Pythona posiada wbudowany atrybut klasy, jakim jest
__module__, a który przechowuje nazwę modułu, w którym dana klasa jest zdefiniowana. - Łącząc to z
sys.modules, możemy pobrać referencję do modułu, w którym ta klasa jest zdefiniowana.
Teraz już jesteś przygotowany do tego, aby zobaczyć w jaki sposób sys.modules jest wykorzystywany w fileinfo.py, czyli przykładowym programie wykorzystanym w rozdziale 5. Poniższy przykład przedstawia fragment kodu.
Przykład.
sys.modules w fileinfo.py
def getFileInfoClass(filename, module=sys.modules[FileInfo.__module__]): #(1)
u"zwraca klasę metadanych pliku na podstawie podanego rozszerzenia"
subclass = "%sFileInfo" % os.path.splitext(filename)[1].upper()[1:] #(2)
return hasattr(module, subclass) and getattr(module, subclass) or FileInfo #(3)
- Jest to funkcja z dwoma argumentami. Argument
filenamejest wymagany, alemodulejest argumentem opcjonalnym i domyślnie wskazuje na moduł, który zawiera klasęFileInfo. Wygląda to nieefektywnie, ponieważ może się wydawać, że Python wykonuje wyrażeniesys.modulesza każdym razem, gdy funkcja zostaje wywołana. Tak naprawdę, Python wykonuje domyślne wyrażenia tylko raz, podczas pierwszego zaimportowania modułu. Jak zobaczymy później, nigdy nie wywołamy tej funkcji z argumentemmodule, więc argumentmodulesłuży nam raczej jako stała na poziomie tej funkcji. - Funkcji tej przyjrzymy się później, po tym, jak zanurkujemy w module
os. Na razie zaufaj, że linia ta sprawia, żesubclassprzechowuje nazwę klasy np.MP3FileInfo. - Już wiemy, że funkcja
getattrzwraca nam referencje do obiektu poprzez nazwę.hasattrjest funkcją uzupełniającą, która sprawdza, czy obiekt posiada określony atrybut. W tym przypadku sprawdzamy, czy moduł posiada określoną klasę (funkcja ta działa na dowolnym obiekcie i dowolnym atrybucie, podobnie jakgetattr). Ten kod możemy na język polski przetłumaczyć w ten sposób: „Jeśli ten moduł posiada klasę o nazwie zawartej w zmiennejsubclass, to ją zwróć, w przeciwnym wypadku zwróć klasęFileInfo”.
Materiały dodatkowe
[edytuj]- Python Tutorial omawia dokładnie, kiedy i jak domyślne argumenty są wyznaczane
- Dokumentacja Python3 moduł
sys