etc./StackOverFlow

전체 경로가 주어진 모듈을 가져오는 방법은 무엇입니까?

청렴결백한 만능 재주꾼 2022. 7. 6. 02:43
반응형

질문자 :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 도 참조하세요.


Sebastian Rittau

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

Daryl Spitzer

모듈을 가져오려면 해당 디렉토리를 환경 변수에 임시 또는 영구적으로 추가해야 합니다.

일시적으로

 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 질문


Miladiouss

최상위 모듈이 파일이 아니지만 __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 속성으로 나타나야 합니다. " 여기에 설명된 대로 .


Sam Grondahl

구성 파일을 특별히 가져오고 싶지 않은 것 같습니다(많은 부작용과 추가 복잡성이 포함됨). 당신은 그것을 실행하고 결과 네임스페이스에 접근할 수 있기를 원합니다. 표준 라이브러리는 runpy.run_path 형식으로 특별히 API를 제공합니다.

 from runpy import run_path settings = run_path("/path/to/file.py")

해당 인터페이스는 Python 2.7 및 Python 3.2 이상에서 사용할 수 있습니다.


ncoghlan

이와 같은 작업을 수행하고 구성 파일이 있는 디렉토리를 Python 로드 경로에 추가한 다음 파일 이름(이 경우 "config")을 미리 알고 있다고 가정하고 일반 가져오기를 수행할 수도 있습니다.

지저분하지만 작동합니다.

 configfile = '~/config.py' import os import sys sys.path.append(os.path.dirname(os.path.expanduser(configfile))) import config

ctcherry

당신은 사용할 수 있습니다

 load_source(module_name, path_to_file)

imp 모듈 의 메소드 .


zuber

로드 또는 가져오기를 의미합니까?

sys.path 목록을 조작하여 모듈에 대한 경로를 지정한 다음 모듈을 가져올 수 있습니다. 예를 들어 다음 위치에 모듈이 있다고 가정합니다.

 /foo/bar.py

당신은 할 수 있습니다:

 import sys sys.path[0:0] = ['/foo'] # Puts the /foo directory at the start of your path import bar

Wheat

@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 .txtimportlib.machinery.SOURCE_SUFFIXES 없기 때문에 로더를 지정하지 않고 spec_from_file_location 을 사용하여 로드할 수 없음을 의미합니다.


Mad Physicist

__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')

Chris Calloway

다음은 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())

나는 그것을 테스트했다. 보기 흉할 수도 있지만 지금까지 모든 버전에서 작동하는 유일한 것입니다.


sorin

동일한 프로젝트에 다른 디렉토리 수단에 스크립트가 있는 경우 다음 방법으로 이 문제를 해결할 수 있습니다.

이 상황에서 utils.pysrc/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

Kumar KS

imp.find_module()imp.load_module() 을 사용하여 지정된 모듈을 로드할 수 있다고 생각합니다. 경로에서 모듈 이름을 분리해야 합니다. 예를 들어 /home/mypath/mymodule.py 를 로드하려면 다음을 수행해야 합니다.

 imp.find_module('mymodule', '/home/mypath/')

...하지만 그것은 일을 끝내야합니다.


Matt

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!

bob_twinkles

이에 특별히 전용 패키지 가 있습니다.

 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도 포함)에서 테스트되었지만 프로젝트 크기에 따라 과도할 수 있습니다.


fny

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

모듈에서 가져온 모듈을 가져올 수 있습니다.


abhimanyu

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의 솔루션이 명령줄에서 작동했지만 프로그램 내부에서는 작동하지 않는다는 것을 발견했습니다.


Redlegjed

나는 당신 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

또는

http://code.google.com/p/import-file/


ubershmekel

주어진 파일 이름에서 모듈을 가져오기 위해 일시적으로 경로를 확장하고 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

Peter Zhu

더 낫다는 말은 아니지만, 완성도를 위해 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)

yoniLavi

이것은 작동해야합니다

 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)

Hengjie

런타임에 패키지 모듈 가져오기(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)

user10370

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)

이 솔루션의 장점은 코드에서 사용하기 위해 가져오려는 모듈의 실제 이름을 알 필요조차 없다는 것입니다. 이는 예를 들어 모듈의 경로가 구성 가능한 인수인 경우에 유용합니다.


Ataxias

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 *

user2760152

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

David

아주 간단한 방법: 상대 경로가 ../../MyLibs/pyfunc.py인 가져오기 파일을 원한다고 가정합니다.

 libPath = '../../MyLibs' import sys if not libPath in sys.path: sys.path.append(libPath) import pyfunc as pf

그러나 가드 없이 그것을 만들면 마침내 매우 긴 경로를 얻을 수 있습니다.


Andrei Keino

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.pytestlib , testlib.blabla.pytestlib_blabla 등).
  • sys.path 또는 검색 경로 저장소에 의존하지 않습니다.
  • 같은 전역 변수 저장 / 복원하는 데 필요하지 않습니다 SOURCE_FILESOURCE_DIR 호출 사이에 tkl_import_module .
  • [ 3.4.x tkl_import_module 호출에서 모듈 네임스페이스를 혼합할 수 있습니다(예: named->local->named 또는 local->named->local 등).
  • [for 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 라이브러리로 이동했습니다. 위의 링크를 참조하세요.


Andry

이것은 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

Benos

이 답변은 "하지만 모듈 이름이 없으면 어떻게 합니까?"라는 주석에 대한 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 있는 경우 이것이 트릭을 수행합니다.


Michael Scott Cuthbert

출처 : http:www.stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path

반응형