Як перевірити, чи імпортовано модуль python?


91

Як перевірити, чи я імпортував модуль десь у коді?

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

Причиною того, що я хотів би перевірити, чи я вже імпортував модуль, є те, що у мене є модуль, який я не хочу імпортувати, оскільки іноді він псує мою програму.


Просто поставте raise SystemError()(або інший виняток на ваш вибір) у верхню частину модуля, який ви не хочете імпортувати. Якщо ж на самому справі імпортувати його де - небудь, ваша програма буде кидати відслідковує і вихід.
larsks

Як у будь-якому випадку просто імпорт модуля псує вашу програму? Це звучить не так імовірно.
Білл Вудгер,


@MartijnPieters Yoiks. І імпорт звучить настільки нейтрально.
Білл Вудгер

Відповіді:


122

Тест на назву модуля у sys.modulesсловнику :

import sys

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

З документації:

Це словник, який відображає імена модулів до вже завантажених модулів.

Зверніть увагу, що importтвердження робить дві речі:

  1. якщо модуль ніколи раніше не імпортувався (== відсутній sys.modules), він завантажується та додається до sys.modules.
  2. Прив’язати 1 або більше імен у поточному просторі імен, що посилаються на об’єкт модуля, або на об’єкти, які є членами простору імен модуля.

Випробування виразу, modulename not in sys.modulesякщо відбувся крок 1. Тестування результату кроку 2 вимагає знання того, який саме importоператор був використаний, оскільки вони встановлювали різні імена для посилання на різні об’єкти:

  • import modulename набори modulename = sys.modules['modulename']
  • import packagename.nestedmoduleнабори packagename = sys.modules['packagename'](незалежно від того, скільки додаткових рівнів ви додали)
  • import modulename as altname набори altname = sys.module['modulename']
  • import packagename.nestedmodule as altname набори altname = sys.modules['packagename.nestedmodule']
  • from somemodule import objectname набори objectname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulenameнабори nestedmodulename = sys.modules['packagename.nestedmodulename'](лише тоді, коли до цього імпорту nestedmodulenameв packagenameпросторі імен не було вказано жодного об’єкта, на цей момент до простору імен батьківського пакета додається додаткове ім’я для вкладеного модуля)
  • from somemodule import objectname as altname набори altname = sys.modules['somemodule'].objectname
  • from packagename import nestedmodulename as altnameнабори altname = sys.modules['packagename.nestedmodulename'](лише тоді, коли до цього імпорту nestedmodulenameв packagenameпросторі імен не було вказано жодного об’єкта, на цей момент до простору імен батьківського пакета додається додаткове ім’я для вкладеного модуля)

Ви можете перевірити, чи існує ім'я, до якого прив'язаний імпортований об'єкт, у даному просторі імен:

# 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'])

Це повідомляє лише про те, що ім’я існує (було пов’язане), а не якщо воно стосується конкретного модуля або об’єкта з цього модуля. Ви можете додатково проаналізувати цей об’єкт або перевірити, чи це той самий об’єкт, що й доступний sys.modules, якщо вам потрібно виключити, що з тих пір ім’я було встановлено на щось інше.


1
Це найкращий спосіб перевірити наявність необхідного пакету всередині функції? Тобто, скажімо, для якоїсь функції потрібен numpyпакет - чи import sysвсередині функції найкраще перевірити, чи вона була імпортована? Під "найкращим" я маю на увазі термін впливу на ефективність, який import sysбуде називатися тоді кожного разу, коли функція буде викликана. Спасибі
осоромлені

@Confounded ви можете просто імпортувати sys поза функцією, якщо це вас турбує. Не те, що import sysбудь-яким чином є дорогим; sysзавжди існує, він за замовчуванням вже завантажений. Але для додаткового пакету: просто імпортуйте пакет . Визначте ImportErrorвиняток, якщо пакет не встановлений, і встановіть прапорець, який вказує, що він встановлений, коли імпорт вдається. Після цього ви можете використовувати прапор, щоб повідомити про своє використання необов’язкової залежності.
Мартін Пітерс

@Confounded name in sys.modulesТест корисний лише в тому випадку, якщо ви не хочете імпортувати .
Мартін Пітерс

24

До прийнятих відповідей sys.modules я додав би одне застереження, щоб бути обережними щодо перейменування модулів при імпорті:

>>> import sys
>>> import datetime as dt
>>> 'dt' in sys.modules
False
>>> 'datetime' in sys.modules
True

18

використовуйте sys.modules, щоб перевірити, чи імпортовано модуль (я використовую unicodedata як приклад):

>>> import sys
>>> 'unicodedata' in sys.modules
False
>>> import unicodedata
>>> 'unicodedata' in sys.modules
True

5

sys.modules містить усі модулі, що використовуються в будь-якому місці поточного екземпляра інтерпретатора, і тому відображається при імпорті в будь-який інший модуль Python.

dir() перевіряє, чи було ім'я визначено у поточному просторі імен.

Поєднання двох є більш безпечним, ніж кожен окремий, і працює до тих пір, поки ви не визначили copyсебе.

if ('copy' in sys.modules) and ('copy' in dir()):

0
if "sys" not in dir():
  print("sys not imported!")

Це лише перевіряє, чи імпортувався модуль у поточному просторі імен. Також sysможе бути що завгодно, а не просто модуль.
vaultah
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.