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ł
sys
zawiera informacje dotyczące systemu jak np. wersję uruchomionego Pythona (sys.version
lubsys.version_info
) i opcje dotyczące systemu np. maksymalna dozwolona głębokość rekurencji (sys.getrecursionlimit()
isys.setrecursionlimit()
). sys.modules
jest 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.modules
zawiera 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
filename
jest wymagany, alemodule
jest 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.modules
za 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 argumentmodule
sł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, żesubclass
przechowuje nazwę klasy np.MP3FileInfo
. - Już wiemy, że funkcja
getattr
zwraca nam referencje do obiektu poprzez nazwę.hasattr
jest 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