파이썬 모듈을 가져 오지 않고 존재하는지 확인하는 방법


179

파이썬 모듈을 가져 오지 않고 존재하는지 알아야합니다.

존재하지 않는 항목 가져 오기 (원하는 항목이 아님) :

try:
    import eggs
except ImportError:
    pass

4
궁금한 점이 있는데 가져 오기를 사용하면 어떤 단점이 있습니까?

15
모듈에 부작용이있는 경우 import를 호출하면 원하지 않는 결과가 발생할 수 있습니다. 따라서 먼저 실행할 파일 버전을 확인하려면 아래 답변을 확인하고 나중에 가져 오기를 수행하십시오. 부작용이있는 모듈을 작성하는 것이 좋습니다. 그러나 우리는 모두 성인이며 코드 작성의 위험성에 대한 자체 결정을 내릴 수 있습니다.
yarbelk


1
@ArtOfWarfare 난 그냥 폐쇄 것을 질문 당신의 중복으로 연결 하나. 이 질문이 더 명확하고 여기에 제안 된 솔루션이 다른 모든 질문보다 낫기 때문입니다. 차라리 사람들이이 문제를 해결하는 것보다이 더 나은 솔루션에 대한 답변을 원하는 사람을 지적하고 싶습니다.
Bakuriu

7
@Chuck 또한 모듈이 존재할 수 있지만 자체적으로 가져 오기 오류가있을 수 있습니다. 위의 코드에서와 같이 ImportErrors를 잡으면 실제로 존재하지만 오류가있는 경우 모듈이 존재하지 않음을 나타낼 수 있습니다.
Michael Barton

답변:


199

파이썬 2

import가 python2에서 무언가를 찾을 수 있는지 확인하려면 다음을 사용하십시오. imp

import imp
try:
    imp.find_module('eggs')
    found = True
except ImportError:
    found = False

점선으로 된 수입품을 찾으려면 다음을 수행해야합니다.

import imp
try:
    spam_info = imp.find_module('spam')
    spam = imp.load_module('spam', *spam_info)
    imp.find_module('eggs', spam.__path__) # __path__ is already a list
    found = True
except ImportError:
    found = False

pkgutil.find_loaderpython3 부분과 거의 동일하거나 더 많이 사용할 수 있습니다

import pkgutil
eggs_loader = pkgutil.find_loader('eggs')
found = eggs_loader is not None

파이썬 3

Python3 ≤ 3.3

를 사용해야합니다 importlib.이 작업을 수행 한 방법은 다음과 같습니다.

import importlib
spam_loader = importlib.find_loader('spam')
found = spam_loader is not None

내 기대는 로더를 찾을 수 있다면 존재한다는 것입니다. 어떤 로더를 수용할지 필터링하는 것과 같이 좀 더 똑똑 할 수도 있습니다. 예를 들면 다음과 같습니다.

import importlib
spam_loader = importlib.find_loader('spam')
# only accept it as valid if there is a source file for the module - no bytecode only.
found = issubclass(type(spam_loader), importlib.machinery.SourceFileLoader)

Python3 ≥ 3.4

Python3.4에서는 importlib.find_loader 파이썬 문서 가 더 이상 사용되지 않습니다 importlib.util.find_spec. 권장되는 방법은 importlib.util.find_spec입니다. 같은 다른 importlib.machinery.FileFinder파일이 있는데, 특정 파일을로드 한 후에 유용합니다. 그것들을 사용하는 방법을 알아내는 것은 이것의 범위를 벗어납니다.

import importlib
spam_spec = importlib.util.find_spec("spam")
found = spam_spec is not None

이것은 상대 수입에도 적용되지만 시작 패키지를 제공해야하므로 다음을 수행 할 수도 있습니다.

import importlib
spam_spec = importlib.util.find_spec("..spam", package="eggs.bar")
found = spam_spec is not None
spam_spec.name == "eggs.spam"

나는 이것을하는 이유가 있다고 확신하지만 그것이 무엇인지 잘 모르겠습니다.

경고

하위 모듈을 찾으려고 할 때 상위 모듈을 가져옵니다 ( 위의 모든 방법에 대해)!

food/
  |- __init__.py
  |- eggs.py

## __init__.py
print("module food loaded")

## eggs.py
print("module eggs")

were you then to run
>>> import importlib
>>> spam_spec = importlib.find_spec("food.eggs")
module food loaded
ModuleSpec(name='food.eggs', loader=<_frozen_importlib.SourceFileLoader object at 0x10221df28>, origin='/home/user/food/eggs.py')

이 문제를 해결하는 것에 대한 의견

감사의 말

  • importlib에 대한 @rvighne
  • 파이썬 3.3 이상에서 @ lucas-guido find_loader
  • Python2.7의 pkgutils.find_loader 동작에 대한 @enpenax

3
이것은 최상위 모듈에서만 작동하며에서는 작동하지 않습니다 eggs.ham.spam.
hemflit 2016 년

3
당신이 찾으려면 @hemflit spameggs.ham사용할 것imp.find_module('spam', ['eggs', 'ham'])
gitaarik

5
+1,하지만 imp되어 사용되지 찬성 importlib3 파이썬
rvighne

4
가져온 모듈에 실제 "ImportError"가 포함되어 있으면 어떻게됩니까? 그것이 저에게 일어난 일입니다. 그러면 모듈이 존재하지만 "발견"되지 않습니다.
enpenax

1
1 년 후 나는 위에서 언급 한 것과 같은 문제를 겪고 파이썬 2에 대한 솔루션을 파고 들었습니다 pkgutil.find_loader("my.package.module"). 패키지 / 모듈이 존재하고 존재 None하지 않으면 로더를 반환합니다 . ImportError를
가리면

13

yarbelk의 응답을 사용한 후에는 import하지 않아도되도록했습니다 ìmp.

try:
    __import__('imp').find_module('eggs')
    # Make things with supposed existing module
except ImportError:
    pass

장고에서 유용합니다 settings.py.


4
이 마스크는 모듈에서 가져 오기 오류를 가져 오기 때문에 실제로 오류를 찾기가 어렵습니다.
enpenax

1
Downvote는 나쁜 생각입니다. 좋은 실천은 "항상 기록 된 오류 기록"입니다. 원하는 방식으로 작성한 후의 예입니다.
Zulu

2
가져온 모듈이 ImportError와 함께 라인 1에서 실패하고 try catch로 인해 자동으로 실패하면 어떻게 오류를 기록합니까?
enpenax

나는 실생활에서 마스킹-가져 오기-오류 문제에 부딪 쳤으며, 테스트에 실패했기 때문에 나빴습니다!
David 주어진

누군가가 다른 모듈에 monkeypatch을 실행하는 데 그 오류를 사용했다 어디했다 그 ... 그게 다 퉜다 광기 찾을 수
yarbelk

13

파이썬 3> = 3.6 : ModuleNotFoundError

Python 3.6ModuleNotFoundError 에 도입 되었으며이 목적으로 사용할 수 있습니다

try:
    import eggs
except ModuleNotFoundError:
    # Error handling
    pass

모듈 또는 상위 모듈 중 하나를 찾을 수없는 경우 오류가 발생 합니다. 그래서

try:
    import eggs.sub
except ModuleNotFoundError as err:
    # Error handling
    print(err)

외모가 좋아하는 메시지를 인쇄 할 No module named 'eggs'경우 생성 eggs모듈을 찾을 수 없습니다를; 그러나 모듈 No module named 'eggs.sub'sub찾을 수 없지만 eggs패키지를 찾을 수 있는 경우 와 같은 것을 인쇄합니다 .

참조 가져 오기 시스템 설명서를 .ModuleNotFoundError


1
패키지가 존재하는 경우 패키지를 가져 오기 때문에 질문에 답변하지 않습니다
divenex

11

ImportError에 의존하지 않는 Python 2

현재 답변이 업데이트 될 때까지 Python 2 의 길은 다음과 같습니다.

import pkgutil
import importlib

if pkgutil.find_loader(mod) is not None:
    return importlib.import_module(mod)
return None

왜 또 다른 대답?

많은 답변이을 잡는 것을 사용합니다 ImportError. 그것의 문제는 우리가 무엇을 던지는 지 알 수 없다는 것입니다.ImportError 입니다.

당신이 가져 오는 경우 존재하지 않는 모듈을하고있을 발생 ImportError(예 : 오타 라인 1) 귀하의 모듈을, 결과는 모듈이 존재하지 않는다고 할 것이다. 모듈이 존재하고 ImportError잡히고 자동으로 실패하는 것을 파악하기 위해서는 상당한 양의 역 추적이 필요합니다 .


명확하지 않을 수도 있지만 첫 번째 코드 블록을 제외한 모든 코드에 의존하지는 않습니다 ImportError. 명확하지 않은 경우 편집하십시오.
yarbelk

처음 두 개의 Python 2 예제에서 ImportError catch를 사용하는 것을 볼 수 있습니다. 그렇다면 왜 거기에 있습니까?
enpenax

3
mod == 'not_existing_package.mymodule'인 경우 ImportError가 발생합니다. 내 전체보기 아래 솔루션
마르신 Raczyński

1
물론 가져 오기 오류가 발생합니다. 모듈이 존재하지 않으면 가져 오기 오류가 발생합니다. 그렇게하면 필요할 때 잡을 수 있습니다. 다른 솔루션의 문제점은 다른 오류를 마스킹한다는 것입니다.
enpenax

시도 / 제외한다고해서 기록하거나 확인해서는 안됩니다. 기본 역 추적을 완전히 포착하고 원하는 것을 수행 할 수 있습니다.
Zulu

8

하나의 라이너로서의 go_as의 답변

 python -c "help('modules');" | grep module

6

커맨드 라인 에서 모듈이로드되었는지 확인하는 방법을 찾고있는 동안이 질문을 보았고 나에게 오는 모듈에 대한 내 생각을 공유하고 싶습니다.

Linux / UNIX 스크립트 파일 방법 : 파일 작성 module_help.py:

#!/usr/bin/env python

help('modules')

그런 다음 실행 파일인지 확인하십시오. chmod u+x module_help.py

그리고 그것을 전화 pipegrep:

./module_help.py | grep module_name

내장 된 도움말 시스템을 호출하십시오 . (이 기능은 대화식으로 사용하기위한 것입니다 .) 인수가 없으면 대화식 도움말 시스템이 인터프리터 콘솔에서 시작됩니다. 인수가 string 인 경우, 문자열은 모듈 , 함수, 클래스, 메소드, 키워드 또는 문서 주제 의 이름으로 조회되고 도움말 페이지가 콘솔에 인쇄됩니다. 인수가 다른 종류의 객체 인 경우 객체의 도움말 페이지가 생성됩니다.

대화식 방법 : 콘솔로드python

>>> help('module_name')

q
python 대화식 세션을 종료하려면 Ctrl+ 를 눌러 독서 를 종료하면D

Windows 스크립트 파일 방법 은 Linux / UNIX와 호환되며 전체적으로 더 좋습니다 .

#!/usr/bin/env python

import sys

help(sys.argv[1])

명령에서 다음과 같이 호출하십시오.

python module_help.py site  

출력 :

모듈 사이트에 대한 도움말 :

NAME site-타사 패키지의 모듈 검색 경로를 sys.path에 추가합니다.

FILE /usr/lib/python2.7/site.py

MODULE DOCS http://docs.python.org/library/site

DESCRIPTION
...
:

q대화식 모드를 종료 하려면을 눌러야 합니다.

알 수없는 모듈 사용 :

python module_help.py lkajshdflkahsodf

출력 :

'lkajshdflkahsodf'에 대한 Python 설명서가 없습니다.

종료합니다.


5

pkgutil기능 중 하나를 사용하십시오 ( 예 :

from pkgutil import iter_modules

def module_exists(module_name):
    return module_name in (name for loader, name, ispkg in iter_modules())


4

모든 모듈을 가져오고 실패한 모듈과 작동중인 모듈을 알려주는 작은 스크립트를 작성할 수 있습니다.

import pip


if __name__ == '__main__':
    for package in pip.get_installed_distributions():
        pack_string = str(package).split(" ")[0]
        try:
            if __import__(pack_string.lower()):
                print(pack_string + " loaded successfully")
        except Exception as e:
            print(pack_string + " failed with error code: {}".format(e))

산출:

zope.interface loaded successfully
zope.deprecation loaded successfully
yarg loaded successfully
xlrd loaded successfully
WMI loaded successfully
Werkzeug loaded successfully
WebOb loaded successfully
virtualenv loaded successfully
...

경고의 말로 모든 것을 가져 오려고 시도 PyYAML failed with error code: No module named pyyaml하므로 실제 가져 오기 이름이 yaml이기 때문에 같은 것을 볼 수 있습니다 . 당신이 당신의 수입을 알고있는 한 이것은 당신을 위해 속임수를해야합니다.


3

이 도우미 함수를 작성했습니다.

def is_module_available(module_name):
    if sys.version_info < (3, 0):
        # python 2
        import importlib
        torch_loader = importlib.find_loader(module_name)
    elif sys.version_info <= (3, 3):
        # python 3.0 to 3.3
        import pkgutil
        torch_loader = pkgutil.find_loader(module_name)
    elif sys.version_info >= (3, 4):
        # python 3.4 and above
        import importlib
        torch_loader = importlib.util.find_spec(module_name)

    return torch_loader is not None

2

importlib직접 사용할 수도 있습니다

import importlib

try:
    importlib.import_module(module_name)
except ImportError:
    # Handle error

실제로 가져 오는 데 문제가 있습니다. 부작용 및 모든
yarbelk

2

부모 패키지를 가져 오지 않고 "dotted module"을 가져올 수 있는지 확실하게 확인할 수있는 방법이 없습니다. 이것을 말하면, "파이썬 모듈이 존재하는지 확인하는 방법"이라는 문제에 대한 많은 해결책이 있습니다.

아래 솔루션은 가져온 모듈이 존재하더라도 ImportError가 발생할 수있는 문제를 해결합니다. 그 상황을 모듈이 존재하지 않는 상황과 구별하고 싶습니다.

파이썬 2 :

import importlib
import pkgutil
import sys

def find_module(full_module_name):
    """
    Returns module object if module `full_module_name` can be imported. 

    Returns None if module does not exist. 

    Exception is raised if (existing) module raises exception during its import.
    """
    module = sys.modules.get(full_module_name)
    if module is None:
        module_path_tail = full_module_name.split('.')
        module_path_head = []
        loader = True
        while module_path_tail and loader:
            module_path_head.append(module_path_tail.pop(0))
            module_name = ".".join(module_path_head)
            loader = bool(pkgutil.find_loader(module_name))
            if not loader:
                # Double check if module realy does not exist
                # (case: full_module_name == 'paste.deploy')
                try:
                    importlib.import_module(module_name)
                except ImportError:
                    pass
                else:
                    loader = True
        if loader:
            module = importlib.import_module(full_module_name)
    return module

파이썬 3 :

import importlib

def find_module(full_module_name):
    """
    Returns module object if module `full_module_name` can be imported. 

    Returns None if module does not exist. 

    Exception is raised if (existing) module raises exception during its import.
    """
    try:
        return importlib.import_module(full_module_name)
    except ImportError as exc:
        if not (full_module_name + '.').startswith(exc.name + '.'):
            raise

1

django.utils.module_loading.module_has_submodule에서


import sys
import os
import imp

def module_has_submodule(package, module_name):
    """
    check module in package
    django.utils.module_loading.module_has_submodule
    """
    name = ".".join([package.__name__, module_name])
    try:
        # None indicates a cached miss; see mark_miss() in Python/import.c.
        return sys.modules[name] is not None
    except KeyError:
        pass
    try:
        package_path = package.__path__   # No __path__, then not a package.
    except AttributeError:
        # Since the remainder of this function assumes that we're dealing with
        # a package (module with a __path__), so if it's not, then bail here.
        return False
    for finder in sys.meta_path:
        if finder.find_module(name, package_path):
            return True
    for entry in package_path:
        try:
            # Try the cached finder.
            finder = sys.path_importer_cache[entry]
            if finder is None:
                # Implicit import machinery should be used.
                try:
                    file_, _, _ = imp.find_module(module_name, [entry])
                    if file_:
                        file_.close()
                    return True
                except ImportError:
                    continue
            # Else see if the finder knows of a loader.
            elif finder.find_module(name):
                return True
            else:
                continue
        except KeyError:
            # No cached finder, so try and make one.
            for hook in sys.path_hooks:
                try:
                    finder = hook(entry)
                    # XXX Could cache in sys.path_importer_cache
                    if finder.find_module(name):
                        return True
                    else:
                        # Once a finder is found, stop the search.
                        break
                except ImportError:
                    # Continue the search for a finder.
                    continue
            else:
                # No finder found.
                # Try the implicit import machinery if searching a directory.
                if os.path.isdir(entry):
                    try:
                        file_, _, _ = imp.find_module(module_name, [entry])
                        if file_:
                            file_.close()
                        return True
                    except ImportError:
                        pass
                # XXX Could insert None or NullImporter
    else:
        # Exhausted the search, so the module cannot be found.
        return False

이것은 파이썬을 프로그래밍 할 때 표준 질문을 충족합니다 : WWDD (Django Do는 무엇입니까?)
yarbelk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.