Jak uzyskać odniesienie do modułu wewnątrz samego modułu?

158

Jak uzyskać odwołanie do modułu z tego modułu? Jak mogę również uzyskać odniesienie do pakietu zawierającego ten moduł?

Ram Rachum
źródło
7
Podejrzewam, że możesz zadawać to pytanie, ponieważ masz zmienną w zakresie modułu (np. BLAH = 10 poza funkcją lub klasą), a następnie zmienną klasy / funkcji o nazwie BLAH i chcesz ją rozróżnić. Tutaj ważne pytanie brzmi: czy to konieczne? Reguły zakresu są notorycznie podatne na pomyłki, zwłaszcza przez „idiotę”, który odbiera Twój kod po Tobie (tj. 6 miesięcy później). Takie sztuczki rzadko są potrzebne; Staram się ich całkowicie unikać, ponieważ często są mylące i błędnie modyfikowane później.
Kevin J. Rice
2
@ KevinJ.Rice „idiota, który odbiera Twój kod po tobie (czyli 6 miesięcy później)” zrobił mój dzień!
arctelix
8
Kogo obchodzi, dlaczego zadaje to pytanie? Jest wiele ważnych powodów, aby to zrobić.
Christopher Barber
Musi zostać zamknięty. Zbyt przydatne.
mlvljr

Odpowiedzi:

211
import sys
current_module = sys.modules[__name__]
truppo
źródło
3
poza tym nie będzie to całkiem poprawne, jeśli moduł zostanie przeładowany; Nie sądzę, aby było miejsce, w którym gwarantowane jest zachowanie odniesienia, gdyby tak było, ponowne ładowanie naprawdę nie zadziałałoby, prawda?
Dima Tisnek
14
Ponowne ładowanie powoduje ponowne użycie tego samego obiektu modułu; nie jest tworzony nowy obiekt modułu, więc nadal jest poprawny w obliczu ponownego ładowania.
bukzor
18

Jeszcze jedna technika, która nie importuje modułu sys i prawdopodobnie - zależy od twojego gustu - prostsza:

current_module = __import__(__name__)

Pamiętaj, że nie ma importu. Python importuje każdy moduł tylko raz.

Uri
źródło
Wydaje się, że to naprawdę dobry sposób na uniknięcie importowania sys. Poza tym, że czytanie jest nieco sprzeczne z intuicją, czy są jakieś potencjalne wady tego podejścia?
JeremyDouglass
@JeremyDouglass. Nie, że jestem świadomy. import to legalna, udokumentowana, wbudowana funkcja (jedyna funkcja xx ). Możesz go zastąpić pakietem „importlib” (musisz go zaimportować). Może - nigdy mi się nie zdarzyło - mógłbyś mieć problem z importem względnym / bezwzględnym, jeśli moduł o tej samej nazwie jest dostępny w sys.path, w takim przypadku możesz go rozwiązać za pomocą argumentu „level” funkcji.
Uri
16

Jeśli masz klasę w tym module, wówczas __module__właściwością klasy jest nazwa modułu klasy. W ten sposób możesz uzyskać dostęp do modułu za pośrednictwem sys.modules[klass.__module__]. Działa to również w przypadku funkcji.

Michael
źródło
4
Właściwie wydaje się, że (przynajmniej) dla funkcji __module__właściwość nie jest modułem, ale ciągiem znaków; dlatego błąd inspect.getabsfile(func.__module__)kończy się błędem „ TypeError: 'os' nie jest modułem, klasą, metodą, funkcją, elementem śledzenia, ramką ani obiektem kodu ”; podczas gdy inspect.getabsfile(sys.modules[o.__module__])wydaje się minąć.
sdaau
12

Możesz uzyskać nazwę bieżącego modułu za pomocą __name__

Opis modułu można znaleźć w sys.modulessłowniku.

Zobacz dokumentację Pythona

pkit
źródło
1

Możesz przekazać go z zewnątrz:

mymod.init(mymod)

Nie jest to idealne rozwiązanie, ale działa w moim obecnym przypadku użycia.

Sam Watkins
źródło