전체 경로가 지정된 모듈을 가져 오는 방법은 무엇입니까?
전체 경로가 주어진 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()
(파이썬 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 도 참조하세요 .
imp를 사용하는 것보다 sys.path에 경로를 추가하는 장점은 단일 패키지에서 둘 이상의 모듈을 가져올 때 작업을 단순화한다는 것입니다. 예를 들면 :
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
구성 파일 (많은 부작용과 추가 합병증이 포함되어 있음)을 구체적으로 가져오고 싶지 않고 실행하고 결과 네임 스페이스에 액세스 할 수있는 것 같습니다. 표준 라이브러리는 runpy.run_path 형식으로 특별히 API를 제공합니다 .
from runpy import run_path
settings = run_path("/path/to/file.py")
해당 인터페이스는 Python 2.7 및 Python 3.2 이상에서 사용할 수 있습니다.
최상위 모듈이 파일이 아니지만 __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 : Parent module 'mymodule'not loaded, cannot perform relative import"오류가 발생합니다. 따라서로드하기 전에 이름을 바인딩해야합니다. 그 이유는 상대적 가져 오기 시스템의 근본적인 불변이기 때문입니다. "불변 보유는 sys.modules [ 'spam'] 및 sys.modules [ 'spam.foo']가있는 경우 (위의 가져 오기 후) ), 후자는 여기서 논의 된 바와 같이 전자의 foo 속성으로 나타나야합니다 .
또한 이와 같은 작업을 수행하고 구성 파일이있는 디렉토리를 Python로드 경로에 추가 한 다음 파일 이름을 미리 알고 있다고 가정하고이 경우 "config"를 일반 가져 오기를 수행 할 수도 있습니다.
지저분하지만 작동합니다.
configfile = '~/config.py'
import os
import sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config
모듈을 가져 오려면 임시 또는 영구적으로 해당 디렉토리를 환경 변수에 추가해야합니다.
일시적으로
import sys
sys.path.append("/path/to/my/modules/")
import my_module
영구적으로
.bashrc
파일 (리눅스)에 다음 줄을 추가하고 source ~/.bashrc
터미널에서 실행 합니다.
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
크레딧 / 출처 : saarrrr , 또 다른 stackexchange 질문
사용할 수 있습니다
load_source(module_name, path_to_file)
imp 모듈의 메소드 .
@SebastianRittau의 멋진 답변 (Python> 3.4에 대해) 의 약간 수정 된 버전을 생각해 냈습니다 . 이는 spec_from_loader
대신 다음을 사용하는 모듈로 모든 확장자를 가진 파일을로드 할 수 있습니다 spec_from_file_location
.
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
이 방법을 사용하여 파일을,하지만 당신이 그것을 할 수 spec_from_file_location
있기 때문에 로더를 지정하지 않고 .txt
아닙니다 importlib.machinery.SOURCE_SUFFIXES
.
다음은 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())
나는 그것을 시험했다. 추악 할 수 있지만 지금까지 모든 버전에서 작동하는 유일한 버전입니다.
로드 또는 가져 오기를 의미합니까?
sys.path
목록을 조작 하여 모듈 경로를 지정한 다음 모듈을 가져올 수 있습니다. 예를 들어, 다음 위치에있는 모듈이 있습니다.
/foo/bar.py
다음과 같이 할 수 있습니다.
import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar
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:
raise ImportError
import_file('/home/somebody/somemodule.py')
지정된 모듈을 사용 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!
파이썬 모듈 test.py 만들기
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
파이썬 모듈 test_check.py 만들기
from test import Client1
from test import Client2
from test import test3
모듈에서 가져온 모듈을 가져올 수 있습니다.
이것은 작동합니다
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 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의 솔루션은 명령 줄에서 작동했지만 프로그램 내부에서는 작동하지 않았습니다.
더 낫다는 말은 아니지만 완전성을 위해 exec
파이썬 2와 3 모두에서 사용할 수 있는 함수 를 제안하고 싶었습니다 exec
. 전역 범위 또는 내부 범위에서 임의의 코드를 실행할 수 있습니다. 사전으로 제공됩니다.
예를 들어 "/path/to/module
"with the function으로 저장된 모듈 foo()
이있는 경우 다음을 수행하여 실행할 수 있습니다.
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)
주어진 파일 이름에서 모듈을 가져 오려면 일시적으로 경로를 확장하고 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
나는 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/
런타임에 패키지 모듈 가져 오기 (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)
Linux에서는 Python 스크립트가있는 디렉토리에 심볼릭 링크를 추가하면 작동합니다.
즉 :
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
python은 /absolute/path/to/script/module.pyc
내용을 변경하면 생성 하고 업데이트합니다./absolute/path/to/module/module.py
그런 다음 mypythonscript.py에 다음을 포함하십시오.
from module import *
아주 간단한 방법 : 상대 경로가 ../../MyLibs/pyfunc.py 인 파일 가져 오기를 원한다고 가정합니다.
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
하지만 가드없이 성공하면 드디어 아주 긴 길을 얻을 수 있습니다
패키지 importlib
대신 사용하는 간단한 솔루션 imp
(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)
이 솔루션의 장점은 코드에서 사용하기 위해 가져 오려는 모듈의 실제 이름을 알 필요조차 없다는 것 입니다. 이는 모듈의 경로가 구성 가능한 인수 인 경우 유용합니다.
내가 효과가있는 것을 찾을 수 없었기 때문에 답변 목록에 이것을 추가하십시오. 이렇게하면 3.4에서 컴파일 된 (pyd) 파이썬 모듈을 가져올 수 있습니다.
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()
이 답변은 "하지만 모듈 이름이 없으면 어떻게해야합니까?"라는 의견에 대한 Sebastian Rittau의 답변에 대한 보충 자료입니다. 이것은 파일 이름이 주어 졌을 가능성이있는 파이썬 모듈 이름을 얻는 빠르고 더러운 방법입니다. __init__.py
파일이 없는 디렉토리를 찾은 다음 파일 이름으로 되돌릴 때까지 트리 위로 올라갑니다 . Python 3.4 이상 (pathlib 사용)의 경우 Py2 사람들이 "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
일반적으로 있다면 이것이 트릭입니다.
다음을 위해 내 자신의 글로벌 및 이식 가능한 가져 오기 기능을 작성했습니다.
- 두 모듈을 모두 하위 모듈로 가져오고 모듈의 내용을 부모 모듈 (또는 부모 모듈이없는 경우 전역으로)으로 가져올 수 있습니다.
- 파일 이름에 마침표가있는 모듈을 가져올 수 있습니다.
- 모든 확장으로 모듈을 가져올 수 있습니다.
- 기본적으로 확장자가없는 파일 이름 대신 서브 모듈에 대해 독립형 이름을 사용할 수 있습니다.
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)
class TackleGlobalImportModuleState:
parent_modules = []
imported_modules = set()
exec_guards = []
class TackleLocalImportModuleState:
# key: variable token
# value: (<value>, <value globals>)
export_globals = {}
# based on:
# https://stackoverflow.com/questions/3589311/get-defining-class-of-unbound-method-object-in-python-3/25959545#25959545
# https://stackoverflow.com/questions/3589311/get-defining-class-of-unbound-method-object-in-python-3/54597033#54597033
#
def tkl_get_method_class(x, from_module = None):
import inspect
if inspect.ismethod(x):
for cls in inspect.getmro(x.__self__.__class__):
if cls.__dict__.get(x.__name__) is x:
return cls
x = x.__func__ # fallback to __qualname__ parsing
if inspect.isfunction(x):
cls_name = x.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]
#print('tkl_get_method_class:', x, '->', cls_name, '->', inspect.getmodule(x))
try:
cls = getattr(inspect.getmodule(x), cls_name)
except AttributeError:
cls = x.__globals__.get(cls_name)
if isinstance(cls, type):
return cls
return getattr(x, '__objclass__', None) # handle special descriptor objects
# DESCRIPTION:
#
# The function must be expressed separately to correctly resolve base classes
# copy function to be able to fix `globals()` only in those methods which are
# a part of a class been defined from a source module including a base class.
# And if a base class is a part of a different module than the module which
# objects being copied from, then what the base class methods would be
# skipped to fixup the `globals()`.
# In other words a derived and a base class could have be defined in
# different modules and their methods has to be fixed for a correct globals
# reference if and only if a being copied class has been defined in the
# module which members are being copied from. If a class has been defined not
# in the being copied module, then it's member functions must be left as is.
#
def tkl_classcopy(x, from_globals, to_globals):
import inspect
if not inspect.isclass(x):
raise Exception('x must a class: ' + type(x))
cls_copy = type(x.__name__, x.__bases__, dict(x.__dict__))
if id(from_globals) != id(to_globals):
# `dict(...)` to convert from iteratable, based on: https://stackoverflow.com/questions/6586310/how-to-convert-list-of-key-value-tuples-into-dictionary/6586521#6586521
for key, value in dict(inspect.getmembers(cls_copy)).items():
if not key.startswith('__'):
if inspect.isfunction(value):
member_cls = tkl_get_method_class(value)
if member_cls in from_globals:
#print(' tkl_classcopy:', key)
# globals retarget to the destination globals
setattr(cls_copy, key, type(value)(value.__code__, to_globals, value.__name__, value.__defaults__, value.__closure__))
return cls_copy
# to readdress `globals()` in all functions
def tkl_membercopy(x, from_globals, to_globals):
if id(from_globals) != id(to_globals):
import inspect
if inspect.isfunction(x):
return type(x)(x.__code__, to_globals, x.__name__, x.__defaults__, x.__closure__)
elif inspect.isclass(x):
return tkl_classcopy(x, from_globals, to_globals)
return x # return by reference
def tkl_merge_module(from_, to):
import inspect
from_globals = vars(from_)
if inspect.ismodule(to):
to_dict = vars(to)
to_globals = False
else:
to_dict = to
to_globals = True
for from_key, from_value in vars(from_).items():
if not from_key.startswith('__') and from_key not in ['SOURCE_FILE', 'SOURCE_DIR']:
if from_key in to_dict:
to_value = to_dict[from_key]
if id(from_value) != id(to_value):
if not inspect.ismodule(from_value) and not inspect.ismodule(to_value):
if not to_globals:
#print(" tkl_merge_module: ", to.__name__, '<-' , from_key)
var_copy = tkl_membercopy(from_value, from_globals, to_dict)
setattr(to, from_key, var_copy)
else:
#print(" tkl_merge_module: globals() <- ", from_key)
to[from_key] = tkl_membercopy(from_value, from_globals, to_dict)
else:
tkl_merge_module(from_value, to_value)
else:
if not to_globals:
#print(" tkl_merge_module: ", to.__name__,'<-' ,from_key)
var_copy = tkl_membercopy(from_value, from_globals, to_dict)
setattr(to, from_key, var_copy)
else:
#print(" tkl_merge_module: globals() <-", from_key)
to[from_key] = tkl_membercopy(from_value, from_globals, to_dict)
return to
def tkl_get_parent_imported_module_state(ignore_not_scoped_modules):
current_globals = globals()
parent_module = None
parent_scope_info = {}
parent_modules = current_globals['TackleGlobalImportModuleState'].parent_modules
if len(parent_modules) > 0:
parent_module = None
for parent_module_tuple in reversed(parent_modules):
if not ignore_not_scoped_modules or parent_module_tuple[0] != '.':
parent_module = parent_module_tuple[1]
parent_scope_info = parent_module_tuple[2]
parent_members = vars(parent_module)
break
if parent_module is None:
parent_members = current_globals
return (parent_module, parent_members, parent_scope_info)
# to auto export globals from a parent module to a child module on it's import
def tkl_declare_global(var, value, value_from_globals = None, auto_export = True):
import inspect, copy
current_globals = globals()
if value_from_globals is None:
value_from_globals = current_globals
# get parent module state
parent_module, parent_members, parent_scope_info = tkl_get_parent_imported_module_state(False)
# make a global either in a current module or in the globals
if not parent_module is None:
setattr(parent_module, var, value)
else:
parent_members[var] = value
export_globals = current_globals['TackleLocalImportModuleState'].export_globals
export_globals[var] = (value, value_from_globals)
if auto_export:
imported_modules = current_globals['TackleGlobalImportModuleState'].imported_modules
for key, global_value in current_globals.items():
if not key.startswith('__') and key not in ['SOURCE_FILE', 'SOURCE_DIR'] and \
inspect.ismodule(global_value) and global_value in imported_modules: # ignore modules which are not imported by `tkl_import_module`
# make a deepcopy with globals retarget to a child module
var_copy = copy.deepcopy(tkl_membercopy(value, value_from_globals, vars(global_value)))
setattr(global_value, var, var_copy)
return value
# ref_module_name:
# `module` - either import the module file as `module` if the module was not imported before or import locally and membercopy the module content into existed one.
# `.` - import the module file locally and do membercopy the content of the module either into the parent module if it exists or into globals.
# `.module` - the same as `module` but the module must not be imported before.
# `module/` - the same as `module` but the module must be imported before.
# `module.` - the same as `module` and the module can not be merged in the next `module` import (some kind of the `.module` behaviour but for the next import).
# `.module.` - has meaning of the both above.
#
def tkl_import_module(dir_path, module_file_name, ref_module_name = None, inject_attrs = {}, prefix_exec_module_pred = None, use_exec_guard = True):
import os, sys, inspect, copy
if not ref_module_name is None and ref_module_name == '':
raise Exception('ref_module_name should either be None or not empty string')
module_file_path = os.path.normcase(os.path.abspath(os.path.join(dir_path, module_file_name))).replace('\\', '/')
module_name_wo_ext = os.path.splitext(module_file_name)[0]
print('import :', module_file_path, 'as', module_name_wo_ext if ref_module_name is None else ref_module_name, '->', list(((parent_imported_module_name + '//' + parent_imported_module.__name__) if parent_imported_module_name != parent_imported_module.__name__ else parent_imported_module.__name__) for parent_imported_module_name, parent_imported_module, parent_imported_module_info in TackleGlobalImportModuleState.parent_modules))
current_globals = globals()
exec_guards = current_globals['TackleGlobalImportModuleState'].exec_guards
if use_exec_guard:
for guard_module_file_path, imported_module in exec_guards:
if guard_module_file_path == module_file_path.replace('\\', '/'):
# copy globals to the parent module
parent_module, parent_members, parent_scope_info = tkl_get_parent_imported_module_state(False)
if parent_module and 'nomergemodule' in parent_scope_info and parent_scope_info['nomergemodule']:
raise Exception('attempt to merge the module content to the existed module has been declared as not mergable: ' + parent_module.__name__)
if not parent_module is None:
tkl_merge_module(imported_module, parent_module)
else:
imported_module_globals = vars(imported_module)
for key, value in imported_module_globals.items():
if not key.startswith('__') and key not in ['SOURCE_FILE', 'SOURCE_DIR']:
if not inspect.ismodule(value) or key not in parent_members or not inspect.ismodule(parent_members[key]):
#print(' copy: globals()::', key, ' <- ', value)
parent_members[key] = tkl_membercopy(value, imported_module_globals, current_globals)
else:
tkl_merge_module(value, parent_members[key])
return imported_module
# get parent module state
parent_module, parent_members, parent_scope_info = tkl_get_parent_imported_module_state(False)
module_must_not_exist = False
module_must_exist = False
nomerge_module = False
if not ref_module_name is None and ref_module_name != '.':
if ref_module_name.startswith('.'): # module must not been imported before by the name
ref_module_name = ref_module_name[1:]
module_must_not_exist = True
if ref_module_name.endswith('/'): # module must be already imported by the name
ref_module_name = ref_module_name[:-1]
module_must_exist = True
if ref_module_name.endswith('.'): # module must not be merged from others (standalone)
ref_module_name = ref_module_name[:-1]
nomerge_module = True
import_module_name = ref_module_name
if (module_must_not_exist and module_must_exist):
raise Exception('The module can be imported either as `.module` or as `module/`, but not as both at a time: ' + ref_module_name)
else:
import_module_name = module_name_wo_ext
if ref_module_name != '.': # import to a local namespace?
if sys.version_info[0] > 3 or sys.version_info[0] == 3 and sys.version_info[1] >= 4:
import importlib.util, importlib.machinery
import_spec = importlib.util.spec_from_loader(import_module_name, importlib.machinery.SourceFileLoader(import_module_name, module_file_path))
imported_module = importlib.util.module_from_spec(import_spec)
imported_module_globals = vars(imported_module)
parent_modules = parent_members['TackleGlobalImportModuleState'].parent_modules
imported_modules = parent_members['TackleGlobalImportModuleState'].imported_modules
export_globals = current_globals['TackleLocalImportModuleState'].export_globals
# auto export globals at first
for key, value_tuple in export_globals.items():
# make a deepcopy with globals retarget to a child module
setattr(imported_module, key, copy.deepcopy(tkl_membercopy(value_tuple[0], value_tuple[1], imported_module_globals)))
# inject attributes in being imported module
imported_module.SOURCE_FILE = module_file_path
imported_module.SOURCE_DIR = os.path.dirname(module_file_path)
imported_module.TackleGlobalImportModuleState = parent_members['TackleGlobalImportModuleState']
imported_module.TackleLocalImportModuleState = copy.deepcopy(current_globals['TackleLocalImportModuleState'])
imported_module.tkl_get_method_class = parent_members['tkl_get_method_class']
imported_module.tkl_classcopy = parent_members['tkl_classcopy']
imported_module.tkl_membercopy = parent_members['tkl_membercopy']
imported_module.tkl_merge_module = parent_members['tkl_merge_module']
imported_module.tkl_get_parent_imported_module_state = parent_members['tkl_get_parent_imported_module_state']
if 'tkl_declare_global' in parent_members:
imported_module.tkl_declare_global = parent_members['tkl_declare_global']
imported_module.tkl_import_module = parent_members['tkl_import_module']
if 'tkl_source_module' in parent_members:
imported_module.tkl_source_module = parent_members['tkl_source_module']
for attr, val in inject_attrs.items():
setattr(imported_module, attr, val)
is_module_ref_already_exist = False
# update parent state
if parent_module:
# reference a being imported module from a parent module
if hasattr(parent_module, import_module_name) and inspect.ismodule(getattr(parent_module, import_module_name)):
is_module_ref_already_exist = True
else:
# reference a being imported module from globals
if import_module_name in parent_members and inspect.ismodule(parent_members[import_module_name]):
is_module_ref_already_exist = True
if module_must_not_exist:
if is_module_ref_already_exist:
raise Exception('The module reference must not exist as a module before the import: ' + import_module_name)
elif module_must_exist:
if not is_module_ref_already_exist:
raise Exception('The module reference must already exist as a module before the import: ' + import_module_name)
if parent_module:
if not is_module_ref_already_exist:
setattr(parent_module, import_module_name, imported_module)
else:
if not is_module_ref_already_exist:
parent_members[import_module_name] = imported_module
# remember last parent before the module execution because of recursion
parent_modules.append((
import_module_name, imported_module,
{'nomergemodule' : nomerge_module}
))
imported_modules.add(imported_module)
try:
if prefix_exec_module_pred:
prefix_exec_module_pred(import_module_name, module_file_path, imported_module)
# before the `exec_module`
exec_guards.append((module_file_path, imported_module))
import_spec.loader.exec_module(imported_module)
finally:
parent_modules.pop()
# copy the module content into already existed module (behaviour by default, do import as `.module` or `module.` or `.module.` to prevent a merge)
if is_module_ref_already_exist:
if parent_module:
tkl_merge_module(imported_module, getattr(parent_module, import_module_name))
else:
tkl_merge_module(imported_module, parent_members[import_module_name])
else:
# back compatability
import imp
imported_module = imp.load_source(import_module_name, module_file_path)
parent_members[import_module_name] = imported_module
# back compatibility: can not be before the imp module exec
exec_guards.append((module_file_path, imported_module))
else: # import to the global namespace
if parent_module and 'nomergemodule' in parent_scope_info and parent_scope_info['nomergemodule']:
raise Exception('attempt to merge the module content to the existed module has been declared as not mergable: ' + parent_module.__name__)
if sys.version_info[0] > 3 or sys.version_info[0] == 3 and sys.version_info[1] >= 4:
import importlib.util, importlib.machinery
import_spec = importlib.util.spec_from_loader(module_name_wo_ext, importlib.machinery.SourceFileLoader(module_name_wo_ext, module_file_path))
imported_module = importlib.util.module_from_spec(import_spec)
imported_module_globals = vars(imported_module)
parent_modules = parent_members['TackleGlobalImportModuleState'].parent_modules
imported_modules = parent_members['TackleGlobalImportModuleState'].imported_modules
export_globals = current_globals['TackleLocalImportModuleState'].export_globals
parent_export_globals = parent_members['TackleLocalImportModuleState'].export_globals
# auto export globals at first
for key, value_tuple in export_globals.items():
# make a deepcopy with globals retarget to a child module
setattr(imported_module, key, copy.deepcopy(tkl_membercopy(value_tuple[0], value_tuple[1], imported_module_globals)))
# inject attributes in being imported module
imported_module.SOURCE_FILE = module_file_path
imported_module.SOURCE_DIR = os.path.dirname(module_file_path)
imported_module.TackleGlobalImportModuleState = parent_members['TackleGlobalImportModuleState']
imported_module.TackleLocalImportModuleState = copy.deepcopy(current_globals['TackleLocalImportModuleState'])
imported_module.tkl_get_method_class = parent_members['tkl_get_method_class']
imported_module.tkl_classcopy = parent_members['tkl_classcopy']
imported_module.tkl_membercopy = parent_members['tkl_membercopy']
imported_module.tkl_merge_module = parent_members['tkl_merge_module']
imported_module.tkl_get_parent_imported_module_state = parent_members['tkl_get_parent_imported_module_state']
if 'tkl_declare_global' in parent_members:
imported_module.tkl_declare_global = parent_members['tkl_declare_global']
imported_module.tkl_import_module = parent_members['tkl_import_module']
if 'tkl_source_module' in parent_members:
imported_module.tkl_source_module = parent_members['tkl_source_module']
for attr, val in inject_attrs.items():
setattr(imported_module, attr, val)
# remember last parent before the module execution because of recursion
parent_modules.append((import_module_name, imported_module, {}))
imported_modules.add(imported_module)
try:
if prefix_exec_module_pred:
prefix_exec_module_pred(import_module_name, module_file_path, imported_module)
# before the `exec_module`
exec_guards.append((module_file_path, imported_module))
import_spec.loader.exec_module(imported_module)
finally:
last_import_module_state = parent_modules.pop()
# copy globals to the parent module
parent_module, parent_members, parent_scope_info = tkl_get_parent_imported_module_state(False)
if not parent_module is None:
tkl_merge_module(imported_module, parent_module)
else:
imported_module_globals = vars(imported_module) # reget after execution
for key, value in vars(imported_module).items():
if not key.startswith('__') and key not in ['SOURCE_FILE', 'SOURCE_DIR']:
if not inspect.ismodule(value) or key not in parent_members or not inspect.ismodule(parent_members[key]):
#print(' copy: globals()::', key, ' <- ', value)
parent_members[key] = tkl_membercopy(value, imported_module_globals, current_globals)
else:
tkl_merge_module(value, parent_members[key])
else:
# back compatability
import imp
imported_module = imp.load_source(module_name_wo_ext, module_file_path).__dict__
for key, value in imported_module.items():
if not key.startswith('__') and key not in ['SOURCE_FILE', 'SOURCE_DIR']:
parent_members[key] = tkl_membercopy(value, current_globals)
# back compatibility: can not be before the imp module exec
exec_guards.append((module_file_path, imported_module))
return imported_module
# shortcut function
def tkl_source_module(dir_path, module_file_name):
return tkl_import_module(dir_path, module_file_name, '.')
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
를 사용하여 일반적인 파이썬 방식으로 항목 스크립트를로드하려면 sys.path
다음을 수행하십시오.
sys.path.append(<path-to-where-test.py-directory-is>)
import test as tkl
# all functions in the module have has a 'tkl_' prefix, all classes begins by `Tackle`, so we don't need a scope here
tkl.tkl_merge_module(tkl, globals())
# cleanup
tkl = None
sys.path.pop()
# from here start using `tkl_import_module` instead of a usual python import...
파이썬에서 테스트 3.7.4
, 3.2.5
,2.7.16
장점 :
- 두 모듈을 모두 하위 모듈로 가져올 수 있으며 모듈의 내용을 상위 모듈 (또는 상위 모듈이없는 경우 전역으로)으로 가져올 수 있습니다.
- 파일 이름에 마침표가있는 모듈을 가져올 수 있습니다.
- 모든 확장 모듈에서 확장 모듈을 가져올 수 있습니다.
- 기본적으로 확장자가없는 파일 이름 대신 하위 모듈에 대해 독립형 이름을 사용할 수 있습니다 (예 :
testlib.std.py
astestlib
,testlib.blabla.py
astestlib_blabla
등). sys.path
또는 어떤 검색 경로 저장소에 의존하지 않습니다 .- 같은 전역 변수를 저장 / 복원하는 데 필요하지 않습니다
SOURCE_FILE
및SOURCE_DIR
호출 사이tkl_import_module
. - [대한
3.4.x
높은] 중첩의 모듈 네임 스페이스를 함께 사용할 수tkl_import_module
호출 (예 :named->local->named
또는local->named->local
등등을). - [for
3.4.x
and higher]tkl_import_module
(tkl_declare_global
함수를 통해 )를 통해 가져온 모든 자식 모듈로 선언되는 전역 변수 / 함수 / 클래스를 자동으로 내보낼 수 있습니다.
단점 :
- [for
3.3.x
and lower] (코드 복제)tkl_import_module
를 호출하는 모든 모듈에서 선언해야합니다.tkl_import_module
업데이트 1,2 ( 3.4.x
이상 만 해당) :
Python 3.4 이상에서는 최상위 모듈에서 선언 tkl_import_module
하여 각 모듈에서 선언해야하는 요구 사항을 우회 할 수 tkl_import_module
있으며 함수는 한 번의 호출로 모든 하위 모듈에 자신을 주입합니다 (일종의 자체 배포 가져 오기).
업데이트 3 :
가져 오기시 실행 보호를 지원 tkl_source_module
하는 bash에 아날로그 기능이 추가되었습니다 source
(가져 오기 대신 모듈 병합을 통해 구현 됨).
업데이트 4 :
tkl_declare_global
모듈 전역 변수가 하위 모듈의 일부가 아니므로 모듈 전역 변수가 보이지 않는 모든 하위 모듈로 모듈 전역 변수를 자동으로 내보내는 기능 이 추가되었습니다 .
가장 좋은 방법은 공식 문서 ( 29.1. imp — Access the import internals ) 에서 오는 것입니다 .
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()
참고 URL : https://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path
'Development Tip' 카테고리의 다른 글
지역 변수의 메모리가 범위 밖에서 액세스 될 수 있습니까? (0) | 2020.09.27 |
---|---|
자바 스크립트의 개체 비교 (0) | 2020.09.27 |
특정 속성에 대한 LINQ의 Distinct () (0) | 2020.09.27 |
C 전처리 기가“linux”라는 단어를 상수“1”로 해석하는 이유는 무엇입니까? (0) | 2020.09.27 |
utf8_general_ci와 utf8_unicode_ci의 차이점은 무엇입니까? (0) | 2020.09.27 |