이름이 지정된 모듈을 문자열로 가져 오는 방법은 무엇입니까?


543

예를 들어 인수로 명령으로 사용하는 Python 응용 프로그램을 작성 중입니다.

$ python myapp.py command1

응용 프로그램을 확장 가능하게, 즉 주 응용 프로그램 소스를 변경하지 않고도 새 명령을 구현하는 새 모듈을 추가 할 수 있기를 원합니다. 나무는 다음과 같습니다.

myapp/
    __init__.py
    commands/
        __init__.py
        command1.py
        command2.py
    foo.py
    bar.py

따라서 응용 프로그램이 런타임에 사용 가능한 명령 모듈을 찾아서 적절한 모듈을 실행하기를 원합니다.

파이썬은 __import__ 함수를 정의합니다.이 함수는 모듈 이름에 문자열을 사용합니다.

__import __ (이름, 전역 = 없음, 지역 주민 = 없음, 보낸 사람 목록 = (), 수준 = 0)

이 함수는 모듈 이름을 가져오고 주어진 전역 및 지역을 사용하여 패키지 컨텍스트에서 이름을 해석하는 방법을 결정합니다. fromlist는 이름으로 지정된 모듈에서 가져와야하는 오브젝트 또는 서브 모듈의 이름을 제공합니다.

출처 : https://docs.python.org/3/library/functions.html# import

그래서 현재 나는 다음과 같은 것을 가지고있다 :

command = sys.argv[1]
try:
    command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
    # Display error message

command_module.run()

이것은 잘 작동합니다.이 코드로 수행하는 작업을 수행하는 더 관용적 인 방법이 있는지 궁금합니다.

계란이나 확장 점을 사용하고 싶지는 않습니다. 이것은 오픈 소스 프로젝트가 아니며 "플러그인"이있을 것으로 기대하지 않습니다. 요점은 주 응용 프로그램 코드를 단순화하고 새 명령 모듈이 추가 될 때마다 코드를 수정할 필요가 없다는 것입니다.


fromlist = [ "myapp.commands"]는 무엇을합니까?
Pieter Müller 2016

@ PieterMüller : 파이썬 셸에서 다음을 입력하십시오 dir(__import__). fromlist는 "from name import ..."를 에뮬레이트 할 이름 목록이어야합니다.
mawimawi


2019 년 기준으로 검색해야합니다 importlib. stackoverflow.com/a/54956419/687896
Brandt

__import__를 사용하지 말라 Python Doc 에서 importlib.import_module
fcm

답변:


321

2.7 / 3.1보다 오래된 Python에서는 그렇게하는 것이 거의 같습니다.

최신 버전 importlib.import_modulePython 2Python 3을 참조하십시오 .

원한다면 사용할 수도 있습니다 exec.

또는 다음을 수행하여 __import__모듈 목록을 가져올 수 있습니다.

>>> moduleNames = ['sys', 'os', 're', 'unittest'] 
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)

Dive Into Python 에서 직접 추출했습니다 .


7
exec와의 차이점은 무엇입니까?
user1767754

1
__init__해당 모듈을 어떻게 사용할 수 있습니까?
Dorian Dore

7
OP에 대한이 솔루션의 한 가지 문제점은 하나 또는 두 개의 잘못된 "명령"모듈에 대한 예외를 트랩하면 전체 명령 앱이 하나의 예외에서 실패하게한다는 것입니다. 개인적 으로 try에 개별적으로 래핑 된 각 가져 오기 를 반복합니다 .mods = __ import __ () \ neximport ImportError as error : report (error) 잘못된 명령이 수정되는 동안 다른 명령이 계속 작동하도록합니다.
DevPlayer

7
Denis Malinovsky가 지적한 것처럼이 솔루션의 또 다른 문제는 파이썬 문서 자체는을 사용하지 않는 것이 좋습니다 __import__. 2.7 문서 : "이 함수는 파이썬 인터프리터에서 사용하기위한 것이지 일반적인 용도로는 사용하지 않기 때문에 importlib.import_module () ...을 사용하는 것이 좋습니다."python3을 사용할 때, imp모듈은 아래에서 monkut이 언급 한 것처럼이 문제를 해결합니다.
LiavK

2
@JohnWu는 왜 필요합니까 foreach당신이있을 때 for element inmap():)하지만
cowbert

300

Python 2.7 및 3.1 이상에 권장되는 방법은 importlib모듈 을 사용하는 것입니다 .

importlib.import_module (이름, 패키지 = 없음)

모듈을 가져옵니다. name 인수는 절대 또는 상대 용어로 가져올 모듈을 지정합니다 (예 : pkg.mod 또는 ..mod). 이름이 상대적인 용어로 지정된 경우 패키지 인수는 패키지 이름을 해결하기위한 앵커 역할을하는 패키지 이름으로 설정해야합니다 (예 : import_module ( '.. mod', 'pkg.subpkg') pkg.mod를 가져옵니다).

예 :

my_module = importlib.import_module('os.path')

2
어느 출처 나 기관에서 추천합니까?
michuelnik

66
문서는 조언 에 대해 사용하여 __import__위에서 언급 한 모듈에 찬성 기능을.
Denis Malinovsky

8
이것은 가져 오기에 잘 작동합니다 os.path. 방법은 from os.path import *?
Nam G VU

5
나는 여기에 대답을 얻습니다 . stackoverflow.com/a/44492879/248616 즉. 전화globals().update(my_module.__dict)
Nam G VU

2
@NamGVU, 이것은 전역을 오염시키기 때문에 위험한 방법이며 동일한 이름을 가진 식별자를 무시할 수 있습니다. 게시 한 링크에이 코드의 개선 된 버전이 있습니다.
Denis Malinovsky

132

참고 : 임프 는 Python 3.4부터 importlib 를 선호하므로 사용되지 않습니다.

언급했듯이 imp 모듈은 다음과 같은 로딩 기능을 제공합니다.

imp.load_source(name, path)
imp.load_compiled(name, path)

나는 이것을 비슷한 것을 수행하기 전에 사용했습니다.

필자의 경우 필자는 정의 된 메소드로 특정 클래스를 정의했습니다. 모듈을로드하면 클래스가 모듈에 있는지 확인한 다음 해당 클래스의 인스턴스를 다음과 같이 만듭니다.

import imp
import os

def load_from_file(filepath):
    class_inst = None
    expected_class = 'MyClass'

    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])

    if file_ext.lower() == '.py':
        py_mod = imp.load_source(mod_name, filepath)

    elif file_ext.lower() == '.pyc':
        py_mod = imp.load_compiled(mod_name, filepath)

    if hasattr(py_mod, expected_class):
        class_inst = getattr(py_mod, expected_class)()

    return class_inst

2
좋고 간단한 해결책. 나는 비슷한 것을 썼다 : stamat.wordpress.com/dynamic-module-import-in-python 그러나 당신의 몇 가지 결함이 있습니다 : 예외는 어떻습니까? IOError와 ImportError? 먼저 컴파일 된 버전을 확인한 다음 소스 버전을 확인하십시오. 클래스를 기대하면 재사용 가능성이 줄어 듭니다.
stamat

3
대상 모듈에서 MyClass를 구성하는 줄에서 클래스 이름에 중복 참조를 추가합니다. 대신 이미 저장되어 expected_class있으므로 class_inst = getattr(py_mod,expected_name)()대신 할 수 있습니다.
Andrew

1
적절하게 일치하는 바이트 컴파일 파일 (접미사 .pyc 또는 .pyo 포함)이 존재하면 주어진 소스 파일을 구문 분석하는 대신 파일이 사용됩니다 . https://docs.python.org/2/library/imp.html#imp.load_source
cdosborn

1
이 솔루션은 효과가 있습니다. 그러나 imp 모듈은 import lib를 위해 더 이상 사용되지 않습니다. imp "페이지를 참조하십시오 :" ""버전 3.4 이후로 사용되지 않음 : imp 패키지가 importlib를 위해 사용되지 않습니다. ""
Ricardo


15

요즘에는 importlib 을 사용해야합니다 .

소스 파일 가져 오기

문서는 실제로위한 조리법을 제공하고, 그것은 같이 간다 :

import sys
import importlib.util

file_path = 'pluginX.py'
module_name = 'pluginX'

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(module)

당신은 회원 (예를 들어이 기능 "에 액세스 할 수 있습니다이 방법 hello") 모듈에서 pluginX.py이 코드에서 호출되는 - module- 네임 스페이스 아래를; 예, module.hello().

멤버 (예 : " hello") 를 가져 오려면 메모리 내 모듈 목록에 module/ pluginX를 포함시킬 수 있습니다 .

sys.modules[module_name] = module

from pluginX import hello
hello()

패키지 가져 오기

(패키지 가져 오기 예를 들어 , pluginX/__init__.py현재 디렉토리 아래의 것은) 사실 간단하다 :

import importlib

pkg = importlib.import_module('pluginX')

# check if it's all there..
def bla(mod):
    print(dir(mod))
bla(pkg)

3
나중에 sys.modules[module_name] = module가능하게하려면 코드 끝에 추가 하십시오import module_name
Daniel Braun

@DanielBraun 오류가 발생했습니다.> ModuleNotFoundError
Nam G VU

11

현지인이 원하는 경우 :

>>> mod = 'sys'
>>> locals()['my_module'] = __import__(mod)
>>> my_module.version
'2.6.6 (r266:84297, Aug 24 2010, 18:46:32) [MSC v.1500 32 bit (Intel)]'

동일하게 작동합니다 globals()


문서 의 내장에서 locals()함수를 명시 적으로 "이 사전의 내용을 수정할 수 없습니다"고 경고했다.
martineau

9

당신은 사용할 수 있습니다 exec:

exec("import myapp.commands.%s" % command)

exec를 통해 모듈에 대한 핸들을 어떻게 얻습니까? (이 예제에서) .run () 메소드를 호출 할 수 있습니까?
Kamil Kisiel

5
그런 다음 getattr (myapp.commands, command)을 수행하여 모듈에 액세스 할 수 있습니다.
Greg Hewgill

1
... 또는 as command_moduleimport 문의 끝에 추가 한 다음 수행command_module.run()
oxfn

Python 3+의 일부 버전에서 exec 는 소스에서 작성된 결과 참조가 exec ()의 locals () 인수에 저장된다는 이점이 추가 된 함수로 변환되었습니다. 로컬 코드 블록 로컬에서 exec'd 참조를 추가로 분리하려면 빈 dict와 같이 자신의 dict를 제공하고 해당 dict를 사용하여 참조를 참조하거나 해당 dict를 다른 함수에 전달할 수 있습니다. exec (source, gobals (), command1_dict) .... print (command1_dict [ 'somevarible'])
DevPlayer

3

@monkut의 솔루션과 유사하지만 재사용 가능하고 오류 허용 기능은 http://stamat.wordpress.com/dynamic-module-import-in-python/에 설명되어 있습니다 .

import os
import imp

def importFromURI(uri, absl):
    mod = None
    if not absl:
        uri = os.path.normpath(os.path.join(os.path.dirname(__file__), uri))
    path, fname = os.path.split(uri)
    mname, ext = os.path.splitext(fname)

    if os.path.exists(os.path.join(path,mname)+'.pyc'):
        try:
            return imp.load_compiled(mname, uri)
        except:
            pass
    if os.path.exists(os.path.join(path,mname)+'.py'):
        try:
            return imp.load_source(mname, uri)
        except:
            pass

    return mod

1

아래 조각은 나를 위해 일했습니다.

>>>import imp; 
>>>fp, pathname, description = imp.find_module("/home/test_module"); 
>>>test_module = imp.load_module("test_module", fp, pathname, description);
>>>print test_module.print_hello();

쉘 스크립트로 가져 오려면 :

python -c '<above entire code in one line>'

-2

예를 들어, 내 모듈 이름은 jan_module/ feb_module/ 와 같습니다 mar_module.

month = 'feb'
exec 'from %s_module import *'%(month)

-7

다음은 나를 위해 일했습니다.

import sys, glob
sys.path.append('/home/marc/python/importtest/modus')
fl = glob.glob('modus/*.py')
modulist = []
adapters=[]
for i in range(len(fl)):
    fl[i] = fl[i].split('/')[1]
    fl[i] = fl[i][0:(len(fl[i])-3)]
    modulist.append(getattr(__import__(fl[i]),fl[i]))
    adapters.append(modulist[i]())

'modus'폴더에서 모듈을로드합니다. 모듈에는 모듈 이름과 이름이 같은 단일 클래스가 있습니다. 예를 들어, modus / modu1.py 파일은 다음을 포함합니다 :

class modu1():
    def __init__(self):
        self.x=1
        print self.x

결과는 동적으로로드 된 클래스 "어댑터"의 목록입니다.


13
의견에 이유를 제시하지 않고 답변을 묻지 마십시오. 누구에게도 도움이되지 않습니다.
Rebs

왜 이것이 나쁜지 알고 싶습니다.
DevPlayer

내가 파이썬을 처음 접하고 알고 싶어서 나에게도 왜 이것이 나쁜지 알고 싶다.
코스모스

5
이것은 나쁜 파이썬이기 때문에 나쁜 것이 아니라 일반적으로 나쁜 코드이기도합니다. 무엇입니까 fl? for 루프 정의는 지나치게 복잡합니다. 경로는 하드 코딩되어 있습니다 (예를 들어, 관련이 없음). 낙심 한 파이썬 ( __import__)을 사용하고 있습니다 fl[i]. 이것은 기본적으로 읽을 수 없으며, 그렇게 어려운 것은 아니지만 불필요하게 복잡합니다. 단일 라이너로 가장 많이 선정 된 답변을 참조하십시오.
Phil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.