Jak sprawdzić, czy moduł Pythona został zaimportowany?

91

Jak sprawdzić, czy gdzieś w kodzie zaimportowałem moduł?

 if not has_imported("somemodule"):
     print('you have not imported somemodule')

Powodem, dla którego chciałbym sprawdzić, czy już zaimportowałem moduł, jest to, że mam moduł, którego nie chcę importować, ponieważ czasami psuje mój program.

yuval
źródło
Po prostu umieść raise SystemError()(lub inny wybrany przez siebie wyjątek) na górze modułu, którego nie chcesz importować. Jeśli nie faktycznie zaimportować go gdzieś, program wygeneruje traceback i wysiadanie.
larsks 27.05.15
Jak i tak samo zaimportowanie modułu może zepsuć program? Nie brzmi to tak prawdopodobne.
Bill Woodger
1
@BillWoodger: być może ten moduł zmienia stan globalny, którego nie chcesz zmieniać .
Martijn Pieters
@MartijnPieters Yoiks. I importowane dźwięki są tak neutralne.
Bill Woodger

Odpowiedzi:

122

Sprawdź nazwę modułu w sys.modulessłowniku :

import sys

modulename = 'datetime'
if modulename not in sys.modules:
    print 'You have not imported the {} module'.format(modulename)

Z dokumentacji:

Jest to słownik, który mapuje nazwy modułów na moduły, które zostały już załadowane.

Zauważ, że importinstrukcja ma dwie rzeczy:

  1. jeśli moduł nigdy wcześniej nie był importowany (== brak w sys.modules), to jest ładowany i dodawany do sys.modules.
  2. Powiąż 1 lub więcej nazw w bieżącej przestrzeni nazw, które odwołują się do obiektu modułu lub do obiektów, które są elementami członkowskimi przestrzeni nazw modułu.

Wyrażenie modulename not in sys.modulessprawdza, czy miał miejsce krok 1. Testowanie wyniku kroku 2 wymaga znajomości dokładnej importinstrukcji, która została użyta, ponieważ ustawiają różne nazwy w celu odniesienia do różnych obiektów:

  • import modulename zestawy modulename = sys.modules['modulename']
  • import packagename.nestedmodulezestawy packagename = sys.modules['packagename'](bez względu na to, ile dodasz dodatkowych poziomów)
  • import modulename as altname zestawy altname = sys.module['modulename']
  • import packagename.nestedmodule as altname zestawy altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname zestawy objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenamezestawy nestedmodulename = sys.modules['packagename.nestedmodulename'](tylko wtedy, gdy przed tym importem nie było obiektu nazwanego nestedmodulenamew packagenameprzestrzeni nazw, dodatkowa nazwa zagnieżdżonego modułu jest dodawana do przestrzeni nazw pakietu nadrzędnego w tym momencie)
  • from somemodule import objectname as altname zestawy altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnamezestawy altname = sys.modules['packagename.nestedmodulename'](tylko wtedy, gdy przed tym importem nie było obiektu nazwanego nestedmodulenamew packagenameprzestrzeni nazw, dodatkowa nazwa zagnieżdżonego modułu jest dodawana do przestrzeni nazw pakietu nadrzędnego w tym momencie)

Możesz sprawdzić, czy nazwa, do której został przywiązany importowany obiekt, istnieje w danej przestrzeni nazw:

# is this name visible in the current scope:
'importedname' in dir()

# or, is this a name in the globals of the current module:
'importedname' in globals()

# or, does the name exist in the namespace of another module:
'importedname' in globals(sys.modules['somemodule'])

To tylko mówi ci, że nazwa istnieje (została powiązana), a nie jeśli odnosi się do określonego modułu lub obiektu z tego modułu. Możesz dokładniej przyjrzeć się temu obiektowi lub sprawdzić, czy jest to ten sam obiekt, w którym jest dostępny sys.modules, jeśli chcesz wykluczyć, że od tego czasu nazwa została ustawiona na coś zupełnie innego.

Martijn Pieters
źródło
1
Czy to najlepszy sposób na sprawdzenie wymaganego pakietu w funkcji? To znaczy, powiedzmy, że jakaś funkcja wymaga numpypakietu - czy użycie import syswewnątrz funkcji najlepiej sprawdza, czy została zaimportowana? Przez „najlepszy” mam na myśli wpływ na wydajność, jak import sysbędzie wtedy nazywany przy każdym wywołaniu funkcji. Dziękuję
Confounded
@Confounded, możesz po prostu zaimportować sys poza funkcją, jeśli to cię martwi. Nie import sysjest to w żaden sposób drogie; syszawsze istnieje, domyślnie jest już załadowany. Ale w przypadku pakietu opcjonalnego: po prostu zaimportuj pakiet . Wyłap ImportErrorwyjątek, jeśli pakiet nie jest zainstalowany, i ustaw flagę wskazującą, że zostanie zainstalowany, gdy import się powiedzie. Następnie możesz użyć flagi, aby poinformować o użyciu opcjonalnej zależności.
Martijn Pieters
@Confounded name in sys.modulesTest jest przydatny tylko wtedy, gdy nie chcesz importować .
Martijn Pieters
24

Do zaakceptowanych odpowiedzi sys.modules dodałbym jedno zastrzeżenie, aby zachować ostrożność podczas zmiany nazw modułów podczas importu:

>>> import sys
>>> import datetime as dt
>>> 'dt' in sys.modules
False
>>> 'datetime' in sys.modules
True
morvan68
źródło
18

użyj sys.modules, aby sprawdzić, czy moduł został zaimportowany (używam unicodedata jako przykładu):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True
Haresh Shyara
źródło
5

sys.modules zawiera wszystkie moduły używane w dowolnym miejscu w bieżącej instancji interpretera, więc pojawia się, jeśli zostanie zaimportowany do dowolnego innego modułu Pythona.

dir() sprawdza, czy nazwa została zdefiniowana w bieżącej przestrzeni nazw.

Połączenie dwóch jest bezpieczniejsze niż każde oddzielne i działa, o ile nie zdefiniowałeś copysiebie.

if ('copy' in sys.modules) and ('copy' in dir()):
HansW
źródło
0
if "sys" not in dir():
  print("sys not imported!")
rundekugel
źródło
To tylko sprawdza, czy moduł został zaimportowany w bieżącej przestrzeni nazw. Również sysmoże być cokolwiek, a nie tylko moduł.
vaultah