모듈 이름을 문자열로 지정하여 동적으로 가져오려면 어떻게 해야 합니까?
저는 명령을 인수로 사용하는 파이썬 애플리케이션을 작성하고 있습니다. 예를 들면 다음과 같습니다.
$ 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
에서 지정한 모듈에서 가져와야 하는 개체 또는 하위 모듈의 이름을 제공합니다.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_module
Python 2 및 Python 3용.
또는 사용__import__
다음을 수행하여 모듈 목록을 가져올 수 있습니다.
>>> moduleNames = ['sys', 'os', 're', 'unittest']
>>> moduleNames
['sys', 'os', 're', 'unittest']
>>> modules = map(__import__, moduleNames)
파이썬으로 다이빙에서 바로 찢어졌습니다.
Python 2.7 및 3.1 이상에서는 모듈을 사용하는 것이 좋습니다.
importlib.import_module(
name, package=None)
모듈을 가져옵니다.name 인수는 절대 또는 상대적인 용어로 가져올 모듈을 지정합니다(예:
pkg.mod
또는..mod
이름이 상대적인 용어로 지정된 경우 패키지 인수는 패키지 이름을 확인하기 위한 앵커 역할을 할 패키지 이름으로 설정해야 합니다(예:import_module('..mod', 'pkg.subpkg')
가져올 것입니다.pkg.mod
).
예.
my_module = importlib.import_module('os.path')
참고: importlib을 선호하여 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
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)
# Verify contents of the module:
print(dir(module))
서부터여.module
는 를나는모될것다니입객체를 모듈 가 될 것입니다.pluginX
("Module" ("Module")에한 것)pluginX
를 으로써.import pluginX
). 따라서, 예를 들어 a라고 부릅니다.hello
함수는 매정된(파라미터 없음)에 .pluginX
,사용하다module.hello()
.
가져오기"하려면 "" 기능을 사용해야 .from
한 후 하는 "Memory"를 수행합니다.from
가져오기:
sys.modules[module_name] = module
from pluginX import hello
hello()
패키지 가져오기
대신패를가면려져오호출, 키지출▁calling로 전화하기import_module
충분합니다.패키지 폴더가 있다고 가정합니다.pluginX
에서 작업을 수행한 그냥 합니다.
import importlib
pkg = importlib.import_module('pluginX')
# check if it's all there..
print(dir(pkg))
imp 모듈 또는 보다 직접적인 기능을 사용합니다.
다음을 사용할 수 있습니다.
exec("import myapp.commands.%s" % command)
현지인들이 원하는 경우:
>>> 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()
@dumput의 솔루션과 유사하지만 재사용 가능하고 오류 허용성이 있는 솔루션은 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();
셸 스크립트로 가져오려는 경우:
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' 폴더에서 모듈을 로드합니다.모듈에는 모듈 이름과 동일한 이름을 가진 단일 클래스가 있습니다.예: modus/modu1.py 파일에는 다음이 포함됩니다.
class modu1():
def __init__(self):
self.x=1
print self.x
결과는 동적으로 로드된 클래스 "어댑터" 목록입니다.
언급URL : https://stackoverflow.com/questions/301134/how-can-i-import-a-module-dynamically-given-its-name-as-string
'prosource' 카테고리의 다른 글
열거형 내부 목록 이해를 사용하는 Python (0) | 2023.05.13 |
---|---|
일부 컴퓨터에서 트랜잭션 범위가 자동으로 MSDTC로 에스컬레이션됩니까? (0) | 2023.05.08 |
grep을 사용하여 문자열 "hello"가 있는 모든 파일을 현재 디렉터리에서 검색하고 .h 및 .cc 파일만 표시하려면 어떻게 해야 합니까? (0) | 2023.05.08 |
C#에서 Excel 파일을 여는 방법은 무엇입니까? (0) | 2023.05.08 |
첫 번째 항목이 "ID"인 CSV 파일이 Excel에서 손상되었습니다. (0) | 2023.05.08 |