문제

전체 경로가 주어지면 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

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

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

configfile = '~/config.py'

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config

구성 파일(많은 부작용과 추가 합병증이 수반됨)을 구체적으로 가져오고 싶지 않고 실행하고 결과 네임스페이스에 액세스할 수 있기를 원하는 것처럼 들립니다.표준 라이브러리는 이를 위해 특별히 다음과 같은 API를 제공합니다. runpy.run_path:

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

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

당신은 사용할 수 있습니다

load_source(module_name, path_to_file) 

방법 임프 모듈.

최상위 모듈이 파일이 아니지만 __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 속성으로 나타나야 한다는 것입니다." 여기서 논의한대로.

조금 수정된 버전을 가지고 왔습니다 @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())

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

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

일시적으로

import sys
sys.path.append("/path/to/my/modules/")
import my_module

영구적으로

다음 줄을 추가하십시오. .bashrc 파일(리눅스) 및 실행 source ~/.bashrc 터미널에서:

export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"

출처/출처: 사르르, 또 다른 stackexchange 질문

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

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

...하지만 그러면 작업이 완료될 것입니다.

이것은 작동합니다

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)

당신은 사용할 수 있습니다 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!

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 함수는 Python 2와 3 모두에서 사용할 수 있습니다.exec 전역 범위 또는 사전으로 제공되는 내부 범위에서 임의의 코드를 실행할 수 있습니다.

예를 들어, 다음 위치에 모듈이 저장되어 있는 경우 "/path/to/module" 기능으로 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

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

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

나는 다음을 사용하는 패키지를 만들었습니다. 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

파이썬이 만들 것이다 /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) 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()

이 답변은 의견에 응답하는 Sebastian Rittau의 답변에 대한 보충 자료입니다."하지만 모듈 이름이 없다면 어떻게해야합니까?" 이것은 파일 이름이 주어진 Python 모듈 이름을 얻는 빠르고 더러운 방법입니다. __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 일반적으로 이것이 효과가 있습니다.

내 생각에 가장 좋은 방법은 공식 문서(29.1.imp — 가져오기 내부에 액세스합니다.):

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()
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top