전체 경로가 주어진 Python 모듈을 어떻게 로드할 수 있습니까?
파일은 구성 옵션이므로 파일 시스템의 아무 곳에나 있을 수 있습니다.
질문자 :derfred
전체 경로가 주어진 Python 모듈을 어떻게 로드할 수 있습니까?
파일은 구성 옵션이므로 파일 시스템의 아무 곳에나 있을 수 있습니다.
Python 3.5+의 경우:
import importlib.util spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py") foo = importlib.util.module_from_spec(spec) spec.loader.exec_module(foo) foo.MyClass()
Python 3.3 및 3.4의 경우 다음을 사용합니다.
from importlib.machinery import SourceFileLoader foo = SourceFileLoader("module.name", "/path/to/file.py").load_module() foo.MyClass()
(비록 이것은 Python 3.4에서 더 이상 사용되지 않습니다.)
Python 2의 경우:
import imp foo = imp.load_source('module.name', '/path/to/file.py') foo.MyClass()
컴파일된 Python 파일 및 DLL에 대해 동등한 편의 기능이 있습니다.
http://bugs.python.org/issue21436 도 참조하세요.
sys.path에 경로를 추가하는 것(imp 사용보다)의 장점은 단일 패키지에서 둘 이상의 모듈을 가져올 때 작업을 단순화한다는 것입니다. 예를 들어:
import sys # the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py sys.path.append('/foo/bar/mock-0.3.1') from testcase import TestCase from testutils import RunTests from mock import Mock, sentinel, patch
모듈을 가져오려면 해당 디렉토리를 환경 변수에 임시 또는 영구적으로 추가해야 합니다.
import sys sys.path.append("/path/to/my/modules/") import my_module
.bashrc
(또는 대체) 파일에 다음 줄을 추가하고 source ~/.bashrc
(또는 대체)를 실행합니다.
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
크레딧/출처: saarrrr , 또 다른 Stack Exchange 질문
최상위 모듈이 파일이 아니지만 __init__.py가 있는 디렉토리로 패키지된 경우 허용되는 솔루션은 거의 작동하지만 완전히 작동하지는 않습니다. Python 3.5+에서는 다음 코드가 필요합니다('sys.modules'로 시작하는 추가된 줄 참고):
MODULE_PATH = "/path/to/your/module/__init__.py" MODULE_NAME = "mymodule" import importlib import sys spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH) module = importlib.util.module_from_spec(spec) sys.modules[spec.name] = module spec.loader.exec_module(module)
이 줄이 없으면 exec_module이 실행될 때 최상위 __init__.py의 상대 가져오기를 최상위 모듈 이름(이 경우 "mymodule")에 바인딩하려고 시도합니다. 그러나 "mymodule"이 아직 로드되지 않았으므로 "SystemError: 상위 모듈 'mymodule'이 로드되지 않았습니다. 상대 가져오기를 수행할 수 없습니다"라는 오류가 표시됩니다. 따라서 로드하기 전에 이름을 바인딩해야 합니다. 그 이유는 상대 가져오기 시스템의 기본 불변입니다. "불변 유지는 sys.modules['spam'] 및 sys.modules['spam.foo']가 있는 경우(위의 가져오기 ), 후자는 전자의 foo 속성으로 나타나야 합니다. " 여기에 설명된 대로 .
구성 파일을 특별히 가져오고 싶지 않은 것 같습니다(많은 부작용과 추가 복잡성이 포함됨). 당신은 그것을 실행하고 결과 네임스페이스에 접근할 수 있기를 원합니다. 표준 라이브러리는 runpy.run_path 형식으로 특별히 API를 제공합니다.
from runpy import run_path settings = run_path("/path/to/file.py")
해당 인터페이스는 Python 2.7 및 Python 3.2 이상에서 사용할 수 있습니다.
이와 같은 작업을 수행하고 구성 파일이 있는 디렉토리를 Python 로드 경로에 추가한 다음 파일 이름(이 경우 "config")을 미리 알고 있다고 가정하고 일반 가져오기를 수행할 수도 있습니다.
지저분하지만 작동합니다.
configfile = '~/config.py' import os import sys sys.path.append(os.path.dirname(os.path.expanduser(configfile))) import config
로드 또는 가져오기를 의미합니까?
sys.path
목록을 조작하여 모듈에 대한 경로를 지정한 다음 모듈을 가져올 수 있습니다. 예를 들어 다음 위치에 모듈이 있다고 가정합니다.
/foo/bar.py
당신은 할 수 있습니다:
import sys sys.path[0:0] = ['/foo'] # Puts the /foo directory at the start of your path import bar
@SebastianRittau의 멋진 답변 (Python > 3.4의 경우)의 약간 수정된 버전을 spec_from_file_location
. 이를 spec_from_loader
대신 spec_from_loader를 사용하여 확장자를 가진 파일을 모듈로 로드할 수 있습니다.
from importlib.util import spec_from_loader, module_from_spec from importlib.machinery import SourceFileLoader spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py")) mod = module_from_spec(spec) spec.loader.exec_module(mod)
SourceFileLoader
에서 경로를 인코딩할 때의 이점은 기계 가 확장자에서 파일 유형을 알아내려고 시도하지 않는다는 것입니다. 이것은 이 방법을 사용하여 .txt
.txt
가 importlib.machinery.SOURCE_SUFFIXES
없기 때문에 로더를 지정하지 않고 spec_from_file_location
을 사용하여 로드할 수 없음을 의미합니다.
__import__
및 chdir
사용하여 이 작업을 수행할 수 있습니다.
def import_file(full_path_to_module): try: import os module_dir, module_file = os.path.split(full_path_to_module) module_name, module_ext = os.path.splitext(module_file) save_cwd = os.getcwd() os.chdir(module_dir) module_obj = __import__(module_name) module_obj.__file__ = full_path_to_module globals()[module_name] = module_obj os.chdir(save_cwd) except Exception as e: raise ImportError(e) return module_obj import_file('/home/somebody/somemodule.py')
다음은 2.7-3.5 및 아마도 다른 버전의 모든 Python 버전에서 작동하는 일부 코드입니다.
config_file = "/tmp/config.py" with open(config_file) as f: code = compile(f.read(), config_file, 'exec') exec(code, globals(), locals())
나는 그것을 테스트했다. 보기 흉할 수도 있지만 지금까지 모든 버전에서 작동하는 유일한 것입니다.
동일한 프로젝트에 다른 디렉토리 수단에 스크립트가 있는 경우 다음 방법으로 이 문제를 해결할 수 있습니다.
이 상황에서 utils.py
는 src/main/util/
import sys sys.path.append('./') import src.main.util.utils #or from src.main.util.utils import json_converter # json_converter is example method
imp.find_module()
및 imp.load_module()
을 사용하여 지정된 모듈을 로드할 수 있다고 생각합니다. 경로에서 모듈 이름을 분리해야 합니다. 예를 들어 /home/mypath/mymodule.py
를 로드하려면 다음을 수행해야 합니다.
imp.find_module('mymodule', '/home/mypath/')
...하지만 그것은 일을 끝내야합니다.
pkgutil
모듈(특히 walk_packages
메서드)을 사용하여 현재 디렉터리에 있는 패키지 목록을 가져올 수 있습니다. 거기에서 importlib
기계를 사용하여 원하는 모듈을 가져오는 것은 간단합니다.
import pkgutil import importlib packages = pkgutil.walk_packages(path='.') for importer, name, is_package in packages: mod = importlib.import_module(name) # do whatever you want with module now, it's been imported!
이에 특별히 전용 패키지 가 있습니다.
from thesmuggler import smuggle # À la `import weapons` weapons = smuggle('weapons.py') # À la `from contraband import drugs, alcohol` drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py') # À la `from contraband import drugs as dope, alcohol as booze` dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')
Python 버전(Jython 및 PyPy도 포함)에서 테스트되었지만 프로젝트 크기에 따라 과도할 수 있습니다.
Python 모듈 test.py 생성:
import sys sys.path.append("<project-path>/lib/") from tes1 import Client1 from tes2 import Client2 import tes3
Python 모듈 test_check.py 생성:
from test import Client1 from test import Client2 from test import test3
모듈에서 가져온 모듈을 가져올 수 있습니다.
Python 3.4의 이 영역은 이해하기가 매우 어려운 것 같습니다! 그러나 Chris Calloway의 코드를 사용하여 약간의 해킹을 시작하여 작동하는 것을 얻을 수 있었습니다. 다음은 기본 기능입니다.
def import_module_from_file(full_path_to_module): """ Import a module given the full path/filename of the .py file Python 3.4 """ module = None try: # Get module name and path from full path module_dir, module_file = os.path.split(full_path_to_module) module_name, module_ext = os.path.splitext(module_file) # Get module "spec" from filename spec = importlib.util.spec_from_file_location(module_name,full_path_to_module) module = spec.loader.load_module() except Exception as ec: # Simple error printing # Insert "sophisticated" stuff here print(ec) finally: return module
이것은 Python 3.4에서 더 이상 사용되지 않는 모듈을 사용하는 것으로 보입니다. 나는 그 이유를 이해하는 척하지 않지만 프로그램 내에서 작동하는 것 같습니다. 나는 Chris의 솔루션이 명령줄에서 작동했지만 프로그램 내부에서는 작동하지 않는다는 것을 발견했습니다.
나는 당신 imp
를 사용하는 패키지를 만들었습니다. import_file
이라고 부르며 이것이 사용되는 방식입니다:
>>>from import_file import import_file >>>mylib = import_file('c:\\mylib.py') >>>another = import_file('relative_subdir/another.py')
당신은 그것을 얻을 수 있습니다:
http://pypi.python.org/pypi/import_file
또는
주어진 파일 이름에서 모듈을 가져오기 위해 일시적으로 경로를 확장하고 finally 블록 참조에서 시스템 경로를 복원할 수 있습니다.
filename = "directory/module.py" directory, module_name = os.path.split(filename) module_name = os.path.splitext(module_name)[0] path = list(sys.path) sys.path.insert(0, directory) try: module = __import__(module_name) finally: sys.path[:] = path # restore
더 낫다는 말은 아니지만, 완성도를 위해 Python 2와 Python 3 모두에서 사용할 수 exec
exec
사용하면 사전으로 제공되는 전역 범위 또는 내부 범위에서 임의의 코드를 실행할 수 있습니다.
예를 들어, foo()
"/path/to/module
"에 저장된 모듈이 있는 경우 다음을 수행하여 실행할 수 있습니다.
module = dict() with open("/path/to/module") as f: exec(f.read(), module) module['foo']()
이렇게 하면 코드를 동적으로 로드하고 있다는 것이 좀 더 명확해지고 사용자 정의 내장 기능을 제공하는 기능과 같은 몇 가지 추가 기능이 부여됩니다.
그리고 키 대신 속성을 통해 액세스하는 것이 중요하다면 전역에 대한 사용자 정의 dict 클래스를 디자인할 수 있습니다. 이 클래스는 다음과 같이 액세스를 제공합니다.
class MyModuleClass(dict): def __getattr__(self, name): return self.__getitem__(name)
이것은 작동해야합니다
path = os.path.join('./path/to/folder/with/py/files', '*.py') for infile in glob.glob(path): basename = os.path.basename(infile) basename_without_extension = basename[:-3] # http://docs.python.org/library/imp.html?highlight=imp#module-imp imp.load_source(basename_without_extension, infile)
런타임에 패키지 모듈 가져오기(Python 레시피)
http://code.activestate.com/recipes/223972/
################### ## # ## classloader.py # ## # ################### import sys, types def _get_mod(modulePath): try: aMod = sys.modules[modulePath] if not isinstance(aMod, types.ModuleType): raise KeyError except KeyError: # The last [''] is very important! aMod = __import__(modulePath, globals(), locals(), ['']) sys.modules[modulePath] = aMod return aMod def _get_func(fullFuncName): """Retrieve a function object from a full dotted-package name.""" # Parse out the path, module, and function lastDot = fullFuncName.rfind(u".") funcName = fullFuncName[lastDot + 1:] modPath = fullFuncName[:lastDot] aMod = _get_mod(modPath) aFunc = getattr(aMod, funcName) # Assert that the function is a *callable* attribute. assert callable(aFunc), u"%s is not callable." % fullFuncName # Return a reference to the function itself, # not the results of the function. return aFunc def _get_class(fullClassName, parentClass=None): """Load a module and retrieve a class (NOT an instance). If the parentClass is supplied, className must be of parentClass or a subclass of parentClass (or None is returned). """ aClass = _get_func(fullClassName) # Assert that the class is a subclass of parentClass. if parentClass is not None: if not issubclass(aClass, parentClass): raise TypeError(u"%s is not a subclass of %s" % (fullClassName, parentClass)) # Return a reference to the class itself, not an instantiated object. return aClass ###################### ## Usage ## ###################### class StorageManager: pass class StorageManagerMySQL(StorageManager): pass def storage_object(aFullClassName, allOptions={}): aStoreClass = _get_class(aFullClassName, StorageManager) return aStoreClass(allOptions)
imp
패키지 대신 importlib
를 사용하는 간단한 솔루션(Python 2.7에서 테스트되었지만 Python 3에서도 작동해야 함):
import importlib dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py' sys.path.append(dirname) # only directories should be added to PYTHONPATH module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule' module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")
이제 다음과 같이 가져온 모듈의 네임스페이스를 직접 사용할 수 있습니다.
a = module.myvar b = module.myfunc(a)
이 솔루션의 장점은 코드에서 사용하기 위해 가져오려는 모듈의 실제 이름을 알 필요조차 없다는 것입니다. 이는 예를 들어 모듈의 경로가 구성 가능한 인수인 경우에 유용합니다.
Linux에서는 Python 스크립트가 있는 디렉토리에 심볼릭 링크를 추가하면 작동합니다.
즉:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
파이썬 인터프리터는 생성됩니다 /absolute/path/to/script/module.pyc
그리고 당신의 내용을 변경하는 경우를 업데이트합니다 /absolute/path/to/module/module.py
.
그런 다음 mypythonscript.py 파일에 다음을 포함합니다.
from module import *
Sebastian Rittau 의 답변에 추가하려면 : 적어도 CPython 의 경우 pydoc 이 있으며 공식적으로 선언되지는 않았지만 파일 가져오기가 수행하는 작업은 다음과 같습니다.
from pydoc import importfile module = importfile('/path/to/module.py')
추신. 완성도를 위해 작성 시점에 현재 구현에 대한 참조가 있습니다: pydoc.py , 그리고 xkcd 1987 의 맥락에서 문제 21436 에서 언급된 구현 중 어느 것도 사용하지 않는다는 것을 기쁘게 생각합니다. 최소한 말 그대로가 아닙니다.
이렇게 하면 3.4에서 컴파일된(pyd) Python 모듈을 가져올 수 있습니다.
import sys import importlib.machinery def load_module(name, filename): # If the Loader finds the module name in this list it will use # module_name.__file__ instead so we need to delete it here if name in sys.modules: del sys.modules[name] loader = importlib.machinery.ExtensionFileLoader(name, filename) module = loader.load_module() locals()[name] = module globals()[name] = module load_module('something', r'C:\Path\To\something.pyd') something.do_something()
아주 간단한 방법: 상대 경로가 ../../MyLibs/pyfunc.py인 가져오기 파일을 원한다고 가정합니다.
libPath = '../../MyLibs' import sys if not libPath in sys.path: sys.path.append(libPath) import pyfunc as pf
그러나 가드 없이 그것을 만들면 마침내 매우 긴 경로를 얻을 수 있습니다.
importlib
모듈을 기반으로 내 자신의 전역 및 이식 가능한 가져오기 기능을 작성했습니다.
sys.path
또는 검색 경로 저장소에 의존하는 대신 이전에 가져온 모듈을 기반으로 가져오기 순서를 정의할 수 있습니다.예제 디렉토리 구조:
<root> | +- test.py | +- testlib.py | +- /std1 | | | +- testlib.std1.py | +- /std2 | | | +- testlib.std2.py | +- /std3 | +- testlib.std3.py
포함 종속성 및 순서:
test.py -> testlib.py -> testlib.std1.py -> testlib.std2.py -> testlib.std3.py
구현:
최신 변경 사항 저장소: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py
test.py :
import os, sys, inspect, copy SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/') SOURCE_DIR = os.path.dirname(SOURCE_FILE) print("test::SOURCE_FILE: ", SOURCE_FILE) # portable import to the global space sys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directory import tacklelib as tkl tkl.tkl_init(tkl) # cleanup del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist sys.path.pop() tkl_import_module(SOURCE_DIR, 'testlib.py') print(globals().keys()) testlib.base_test() testlib.testlib_std1.std1_test() testlib.testlib_std1.testlib_std2.std2_test() #testlib.testlib.std3.std3_test() # does not reachable directly ... getattr(globals()['testlib'], 'testlib.std3').std3_test() # ... but reachable through the `globals` + `getattr` tkl_import_module(SOURCE_DIR, 'testlib.py', '.') print(globals().keys()) base_test() testlib_std1.std1_test() testlib_std1.testlib_std2.std2_test() #testlib.std3.std3_test() # does not reachable directly ... globals()['testlib.std3'].std3_test() # ... but reachable through the `globals` + `getattr`
testlib.py :
# optional for 3.4.x and higher #import os, inspect # #SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/') #SOURCE_DIR = os.path.dirname(SOURCE_FILE) print("1 testlib::SOURCE_FILE: ", SOURCE_FILE) tkl_import_module(SOURCE_DIR + '/std1', 'testlib.std1.py', 'testlib_std1') # SOURCE_DIR is restored here print("2 testlib::SOURCE_FILE: ", SOURCE_FILE) tkl_import_module(SOURCE_DIR + '/std3', 'testlib.std3.py') print("3 testlib::SOURCE_FILE: ", SOURCE_FILE) def base_test(): print('base_test')
testlib.std1.py :
# optional for 3.4.x and higher #import os, inspect # #SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/') #SOURCE_DIR = os.path.dirname(SOURCE_FILE) print("testlib.std1::SOURCE_FILE: ", SOURCE_FILE) tkl_import_module(SOURCE_DIR + '/../std2', 'testlib.std2.py', 'testlib_std2') def std1_test(): print('std1_test')
testlib.std2.py :
# optional for 3.4.x and higher #import os, inspect # #SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/') #SOURCE_DIR = os.path.dirname(SOURCE_FILE) print("testlib.std2::SOURCE_FILE: ", SOURCE_FILE) def std2_test(): print('std2_test')
testlib.std3.py :
# optional for 3.4.x and higher #import os, inspect # #SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/') #SOURCE_DIR = os.path.dirname(SOURCE_FILE) print("testlib.std3::SOURCE_FILE: ", SOURCE_FILE) def std3_test(): print('std3_test')
출력 ( 3.7.4
):
test::SOURCE_FILE: <root>/test01/test.py import : <root>/test01/testlib.py as testlib -> [] 1 testlib::SOURCE_FILE: <root>/test01/testlib.py import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib'] import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1'] testlib.std2::SOURCE_FILE: <root>/test01/std1/../std2/testlib.std2.py 2 testlib::SOURCE_FILE: <root>/test01/testlib.py import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib'] testlib.std3::SOURCE_FILE: <root>/test01/std3/testlib.std3.py 3 testlib::SOURCE_FILE: <root>/test01/testlib.py dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib']) base_test std1_test std2_test std3_test import : <root>/test01/testlib.py as . -> [] 1 testlib::SOURCE_FILE: <root>/test01/testlib.py import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib'] import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1'] testlib.std2::SOURCE_FILE: <root>/test01/std1/../std2/testlib.std2.py 2 testlib::SOURCE_FILE: <root>/test01/testlib.py import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib'] testlib.std3::SOURCE_FILE: <root>/test01/std3/testlib.std3.py 3 testlib::SOURCE_FILE: <root>/test01/testlib.py dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib', 'testlib_std1', 'testlib.std3', 'base_test']) base_test std1_test std2_test std3_test
3.7.4
, 3.2.5
, 2.7.16
에서 테스트됨
장점 :
testlib.std.py
는 testlib
, testlib.blabla.py
는 testlib_blabla
등).sys.path
또는 검색 경로 저장소에 의존하지 않습니다.SOURCE_FILE
및 SOURCE_DIR
호출 사이에 tkl_import_module
.3.4.x
tkl_import_module
호출에서 모듈 네임스페이스를 혼합할 수 있습니다(예: named->local->named
또는 local->named->local
등).3.4.x
tkl_import_module
tkl_declare_global
함수를 통해)을 통해 가져온 모든 자식 모듈로 선언된 전역 변수/함수/클래스를 자동으로 내보낼 수 있습니다.단점 :
3.3.x
낮은] 선언해야 tkl_import_module
호출 모든 모듈 tkl_import_module
(코드의 중복) 업데이트 1,2 ( 3.4.x
이상에만 해당):
파이썬 3.4에서 이상 할 수 있습니다 선언에 대한 요구 사항 우회 tkl_import_module
선언하여 각 모듈의 tkl_import_module
최고 수준의 모듈과 단일 통화 (가 자기 배포 가져 오기의 일종)의 모든 아이들 모듈 자체를 삽입 할 기능.
업데이트 3 :
source
아날로그로 tkl_source_module
기능을 추가했습니다(가져오기 대신 모듈 병합을 통해 구현).
업데이트 4 :
tkl_declare_global
함수를 추가하여 모듈 전역 변수를 자식 모듈의 일부가 아니기 때문에 모듈 전역 변수가 보이지 않는 모든 자식 모듈로 자동 내보내기합니다.
업데이트 5 :
모든 기능이 Tacklelib 라이브러리로 이동했습니다. 위의 링크를 참조하세요.
이것은 pathlib만 사용하는 두 가지 유틸리티 기능입니다. 경로에서 모듈 이름을 유추합니다.
기본적으로 폴더에서 모든 Python 파일을 재귀적으로 로드하고 init .py를 상위 폴더 이름으로 바꿉니다. 그러나 특정 파일을 선택하기 위해 Path 및/또는 glob을 제공할 수도 있습니다.
from pathlib import Path from importlib.util import spec_from_file_location, module_from_spec from typing import Optional def get_module_from_path(path: Path, relative_to: Optional[Path] = None): if not relative_to: relative_to = Path.cwd() abs_path = path.absolute() relative_path = abs_path.relative_to(relative_to.absolute()) if relative_path.name == "__init__.py": relative_path = relative_path.parent module_name = ".".join(relative_path.with_suffix("").parts) mod = module_from_spec(spec_from_file_location(module_name, path)) return mod def get_modules_from_folder(folder: Optional[Path] = None, glob_str: str = "*/**/*.py"): if not folder: folder = Path(".") mod_list = [] for file_path in sorted(folder.glob(glob_str)): mod_list.append(get_module_from_path(file_path)) return mod_list
이 답변은 "하지만 모듈 이름이 없으면 어떻게 합니까?"라는 주석에 대한 Sebastian Rittau의 답변을 보완한 것입니다. 이것은 파일 이름이 주어졌을 가능성이 있는 파이썬 모듈 이름을 얻는 빠르고 더러운 방법입니다 -- __init__.py
파일이 없는 디렉토리를 찾을 때까지 트리를 올라갔다가 다시 파일 이름으로 바꿉니다. Python 3.4+(pathlib 사용)의 경우 Python 2 사용자가 "imp" 또는 상대 가져오기를 수행하는 다른 방법을 사용할 수 있으므로 의미가 있습니다.
import pathlib def likely_python_module(filename): ''' Given a filename or Path, return the "likely" python module name. That is, iterate the parent directories until it doesn't contain an __init__.py file. :rtype: str ''' p = pathlib.Path(filename).resolve() paths = [] if p.name != '__init__.py': paths.append(p.stem) while True: p = p.parent if not p: break if not p.is_dir(): break inits = [f for f in p.iterdir() if f.name == '__init__.py'] if not inits: break paths.append(p.stem) return '.'.join(reversed(paths))
확실히 개선의 가능성이 있고 선택적 __init__.py
파일은 다른 변경을 필요로 할 수 있지만 __init__.py
있는 경우 이것이 트릭을 수행합니다.
출처 : http:www.stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path
주어진 요소에 클래스를 추가하는 방법은 무엇입니까? (0) | 2022.07.06 |
---|---|
인쇄 기능의 출력을 어떻게 플러시할 수 있습니까? (0) | 2022.07.06 |
JSON 데이터를 파일에 어떻게 쓰나요? (0) | 2022.07.06 |
MVC와 MVVM의 차이점은 무엇입니까? [닫은] (0) | 2022.07.06 |
데이터 프레임을 결합(병합)하는 방법(내부, 외부, 왼쪽, 오른쪽) (0) | 2022.07.06 |