itsource

이름을 문자열로 지정한 모듈을 Import하려면 어떻게 해야 합니까?

mycopycode 2022. 10. 5. 22:35
반응형

이름을 문자열로 지정한 모듈을 Import하려면 어떻게 해야 합니까?

명령어를 인수로 사용하는 Python 어플리케이션을 작성하고 있습니다.예를 들어 다음과 같습니다.

$ python myapp.py command1

어플리케이션의 확장성이 뛰어나기 때문에 메인 어플리케이션 소스를 변경하지 않고 새로운 명령어를 구현하는 새로운 모듈을 추가할 수 있기를 바랍니다.트리는 다음과 같습니다.

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

따라서 응용 프로그램이 실행 시 사용 가능한 명령어모듈을 찾아서 적절한 명령어모듈을 실행했으면 합니다.

Python은 다음과 같이 정의합니다.__import__()모듈명으로 스트링을 사용합니다.

__import__(name, globals=None, locals=None, fromlist=(), level=0)

함수가 모듈을 가져옵니다.name를 사용할 수 있습니다.globals그리고.locals패키지 컨텍스트에서 이름을 해석하는 방법을 결정합니다.fromlist에, 에서 지정된 모듈에서 Import할 필요가 있는 오브젝트 또는 서브모듈의 이름을 나타냅니다.name.

출처 : 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()

이 방법은 잘 작동합니다. 이 코드로 우리가 하고 있는 일을 좀 더 관용적인 방법으로 할 수 있는지 궁금할 뿐입니다.

특히 계란이나 확장 포인트를 사용하고 싶지 않습니다.이것은 오픈 소스 프로젝트가 아니기 때문에 "플러그인"이 있을 것이라고는 생각하지 않습니다.여기서 중요한 것은 메인 어플리케이션코드를 단순화하고 새로운 명령어모듈이 추가될 때마다 변경할 필요가 없어지는 것입니다.

2.7/3.1보다 오래된 Python에서는 거의 그렇게 할 수 있습니다.

새로운 버전에 대해서는, 을 참조해 주세요.importlib.import_modulePython 2 및 Python 3 용입니다.

사용할 수 있습니다.exec당신이 원한다면요.

또는 사용__import__모듈 목록을 Import하려면 다음 절차를 수행합니다.

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

Dive Into Python에서 바로 리핑되었습니다.

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

importlib.import_module(name, package=None)

모듈을 Import합니다.name 인수는 Import할 모듈을 절대 또는 상대 용어로 지정합니다(예:pkg.mod또는..mod이름이 상대적인 용어로 지정되어 있는 경우 패키지 인수는 패키지 이름을 해결하는 앵커로 기능하는 패키지 이름으로 설정해야 합니다(예:import_module('..mod', 'pkg.subpkg')Import하다pkg.mod).

예.

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

주의: importlib는 Python 3.4부터 권장되지 않습니다.

전술한 바와 같이 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

요즘은 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().

하는 를 들어 Import(「」: 「」)hello" ) 를 포함할 수 있습니다.module/pluginX인메모리 모듈목록에서 다음을 수행합니다.

sys.modules[module_name] = module

from pluginX import hello
hello()

패키지 Import

패키지 가져오기(예:pluginX/__init__.py현재 dir 아래에 있는 )는 실제로 간단합니다.

import importlib

pkg = importlib.import_module('pluginX')

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

imp 모듈을 사용하거나 보다 직접적인 함수를 사용합니다.

현지인이 원하는 경우:

>>> 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()

다음을 사용할 수 있습니다.

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

@syslogut의 솔루션과 유사하지만 재사용이 가능하고 오류 허용이 가능한 솔루션은 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

아래 내용이 효과가 있었습니다.

>>>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();

shell-script로 Import하는 경우:

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

다음과 같은 것이 도움이 되었습니다.

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 폴더에서 모듈을 로드합니다.각 모듈에는 모듈 이름과 같은 이름의 클래스가1개 있어요예: modus/modu1.py 파일에는 다음이 포함됩니다.

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

그 결과 동적으로 로드된 클래스 "adapters" 목록이 나타납니다.

언급URL : https://stackoverflow.com/questions/301134/how-to-import-a-module-given-its-name-as-string

반응형