누군가 모듈의 전체 디렉토리를 가져 오는 좋은 방법을 제공 할 수 있습니까?
나는 이와 같은 구조를 가지고있다 :
/Foo
bar.py
spam.py
eggs.py
추가 __init__.py
하고 수행 하여 패키지로 변환하려고했지만 from Foo import *
원하는 방식으로 작동하지 않았습니다.
누군가 모듈의 전체 디렉토리를 가져 오는 좋은 방법을 제공 할 수 있습니까?
나는 이와 같은 구조를 가지고있다 :
/Foo
bar.py
spam.py
eggs.py
추가 __init__.py
하고 수행 하여 패키지로 변환하려고했지만 from Foo import *
원하는 방식으로 작동하지 않았습니다.
답변:
.py
현재 폴더의 모든 python ( ) 파일을 나열하고 __all__
변수로 넣습니다 .__init__.py
from os.path import dirname, basename, isfile, join
import glob
modules = glob.glob(join(dirname(__file__), "*.py"))
__all__ = [ basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
if not os.path.basename(f).startswith('_')
또는 최소한 if not f.endswith('__init__.py')
목록 이해의 끝까지입니다
os.path.isfile(f)
입니다 True
. 즉, 같은 깨진 심볼릭 링크 및 디렉토리를 필터링 할 somedir.py/
(코너의 경우, 나는 ... 인정,하지만 여전히)
from . import *
설정 후에 __all__
는 서브 모듈이 사용 가능하게하려면 .
(예로서 module.submodule1
, module.submodule2
등).
포함 할 __all__
변수를 추가하십시오 __init__.py
.
__all__ = ["bar", "spam", "eggs"]
moduleName.varName
ref). stackoverflow.com/a/710603/248616
2017 년 업데이트 : 아마도 importlib
대신 사용하고 싶을 것입니다.
를 추가하여 Foo 디렉토리를 패키지로 만듭니다 __init__.py
. 그 __init__.py
추가 :
import bar
import eggs
import spam
동적이기를 원하기 때문에 (좋은 아이디어 일 수도 있고 아닐 수도 있음) 모든 py 파일을 list dir로 나열하고 다음과 같이 가져 오십시오.
import os
for module in os.listdir(os.path.dirname(__file__)):
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
del module
그런 다음 코드에서 다음을 수행하십시오.
import Foo
이제 다음을 사용하여 모듈에 액세스 할 수 있습니다
Foo.bar
Foo.eggs
Foo.spam
등 from Foo import *
이름 충돌을 포함하고 하드 코드를 분석 할 수있게 몇 가지 이유에 대한 좋은 생각이 아니다.
__import__
hackish를 발견한다 , 나는 이름을 추가 하고 스크립트의 맨 아래에 __all__
두는 것이 낫다고 생각한다from . import *
__import__
일반용이 아니며 대신 interpreter
사용 importlib.import_module()
합니다.
from . import eggs
에서는 __init__.py
Python을 가져 오기 전에 이전 에 수행해야 했습니다 . 단지와 함께 import eggs
내가 얻을 ModuleNotFoundError: No module named 'eggs'
하려고 할 때 import Foo
에서 main.py
위의 디렉토리에.
Mihail의 답변을 확장하여 파일 경로를 직접 처리하지 않는 것처럼 해킹이 아닌 방법은 다음과 같습니다.
__init__.py
아래에 빈 파일을 만듭니다Foo/
import pkgutil
import sys
def load_all_modules_from_dir(dirname):
for importer, package_name, _ in pkgutil.iter_modules([dirname]):
full_package_name = '%s.%s' % (dirname, package_name)
if full_package_name not in sys.modules:
module = importer.find_module(package_name
).load_module(full_package_name)
print module
load_all_modules_from_dir('Foo')
당신은 얻을 것이다:
<module 'Foo.bar' from '/home/.../Foo/bar.pyc'>
<module 'Foo.spam' from '/home/.../Foo/spam.pyc'>
RuntimeWarning
full_package_name을 전혀 사용하지 않으면 이러한 메시지를 피할 수도 있습니다 importer.find_module(package_name).load_module(package_name)
.
RuntimeWarning
오류는 부모 (일명있는 dirname)을 가져 와서 (논란의 여지는 있지만 추한 방법으로) 피할 수있다. 이를 수행하는 한 가지 방법은- if dirname not in sys.modules: pkgutil.find_loader(dirname).load_module(dirname)
입니다. 물론 dirname
단일 구성 요소 상대 경로 인 경우에만 작동합니다 . 슬래시가 없습니다. 개인적으로 나는 기본 package_name을 사용하는 @Artfunkel의 접근 방식을 선호합니다.
손을 잡아야하는 사람이 일을 할 수없는 초보자에게 적합합니다.
/ home / el / foo 폴더를 만들고 / home / el / foo main.py
아래 에 파일을 만듭니다. 이 코드를 여기에 넣으십시오.
from hellokitty import *
spam.spamfunc()
ham.hamfunc()
디렉토리 만들기 /home/el/foo/hellokitty
__init__.py
아래 에 파일 을 /home/el/foo/hellokitty
만들고이 코드를 넣으 십시오 .
__all__ = ["spam", "ham"]
이 개 파이썬 파일을 확인하십시오 spam.py
및 ham.py
아래/home/el/foo/hellokitty
spam.py 내부에 함수를 정의하십시오.
def spamfunc():
print("Spammity spam")
ham.py 안에 함수를 정의하십시오 :
def hamfunc():
print("Upgrade from baloney")
그것을 실행 :
el@apollo:/home/el/foo$ python main.py
spammity spam
Upgrade from baloney
import *
것은 나쁜 파이썬 코딩 연습으로 간주됩니다. 그것없이 어떻게합니까?
나는이 문제에 스스로 지쳤다. 그래서 automodinit라는 패키지를 작성하여 고쳤다. http://pypi.python.org/pypi/automodinit/ 에서 얻을 수 있습니다 .
사용법은 다음과 같습니다.
automodinit
패키지를 setup.py
종속성에 포함하십시오 .__all__ = [ "다시 작성하겠습니다"] # 위의 줄이나이 줄을 수정하지 마십시오! 가져 오기 automodinit automodinit.automodinit (__ name__, __file__, globals ()) 델 자동 모드 # 당신이 원하는 다른 것은 여기에 갈 수 있습니다, 그것은 수정되지 않습니다.
그게 다야! 이제 모듈을 가져 오면 __all__이 모듈의 .py [co] 파일 목록으로 설정되고 입력 한 것처럼 각 파일을 가져옵니다.
for x in __all__: import x
따라서 "from M import *"의 효과는 "import M"과 정확히 일치합니다.
automodinit
ZIP 아카이브 내부에서 실행하는 것이 행복하므로 ZIP 안전합니다.
닐
나는 꽤 오래된 게시물을 업데이트하고 있다는 것을 알고 있으며을 사용하려고 시도했지만 automodinit
python3의 설정 프로세스가 깨졌습니다. 따라서 Luca의 답변을 바탕 으로이 문제에 대한 .zip과 작동하지 않을 수있는 더 간단한 답변을 찾았으므로 여기에서 공유해야한다고 생각했습니다.
__init__.py
모듈 내 에서 yourpackage
:
#!/usr/bin/env python
import os, pkgutil
__all__ = list(module for _, module, _ in pkgutil.iter_modules([os.path.dirname(__file__)]))
아래의 다른 패키지 내에서 yourpackage
:
from yourpackage import *
그런 다음 패키지 내에 배치 된 모든 모듈을로드하고 새 모듈을 작성하면 자동으로 가져옵니다. 물론 큰 힘을 가지고 조심스럽게 그런 일을하는 것은 큰 책임이 따릅니다.
나는 또한이 문제를 겪었고 이것이 내 해결책이었다.
import os
def loadImports(path):
files = os.listdir(path)
imps = []
for i in range(len(files)):
name = files[i].split('.')
if len(name) > 1:
if name[1] == 'py' and name[0] != '__init__':
name = name[0]
imps.append(name)
file = open(path+'__init__.py','w')
toWrite = '__all__ = '+str(imps)
file.write(toWrite)
file.close()
이 함수 는 폴더의 모든 모듈을 보유 __init__.py
하는 __all__
변수를 포함하는 파일 (제공된 폴더에)을 파일로 만듭니다 .
예를 들어 다음과 같은 폴더 Test
가 있습니다.
Foo.py
Bar.py
스크립트에서 모듈을 가져 오기를 원합니다.
loadImports('Test/')
from Test import *
이 모든 것을 가져옵니다 Test
과 __init__.py
의 파일을 Test
지금 포함됩니다 :
__all__ = ['Foo','Bar']
제안 된 개선 사항이있는 Anurag Uniyal 답변 !
#!/usr/bin/python
# -*- encoding: utf-8 -*-
import os
import glob
all_list = list()
for f in glob.glob(os.path.dirname(__file__)+"/*.py"):
if os.path.isfile(f) and not os.path.basename(f).startswith('_'):
all_list.append(os.path.basename(f)[:-3])
__all__ = all_list
당신의 __init__.py
정의를 참조하십시오 __all__
. 모듈 - 패키지 문서를 말한다
__init__.py
파일은 파이썬 치료 패키지가 들어있는 같은 디렉토리를 만들기 위해 필요합니다; 이는 문자열과 같은 공통 이름을 가진 디렉토리가 나중에 모듈 검색 경로에서 발생하는 유효한 모듈을 실수로 숨기지 않도록하기 위해 수행됩니다. 가장 간단한 경우__init__.py
빈 파일 일 수 있지만__all__
나중에 설명 하는 패키지의 초기화 코드를 실행하거나 변수를 설정할 수도 있습니다....
유일한 해결책은 패키지 작성자가 패키지의 명시적인 색인을 제공하는 것입니다. import 문은 다음 규칙을 사용합니다. 패키지
__init__.py
코드에서 이름이 지정된 목록을 정의하면__all__
import from package *에서 발생할 때 가져와야하는 모듈 이름 목록으로 간주됩니다. 새 버전의 패키지가 릴리스 될 때이 목록을 최신 상태로 유지하는 것은 패키지 작성자의 책임입니다. 패키지 작성자는 패키지에서 *를 가져 오는 데 사용되지 않는 경우이를 지원하지 않기로 결정할 수도 있습니다. 예를 들어 파일sounds/effects/__init__.py
에 다음 코드가 포함될 수 있습니다.
__all__ = ["echo", "surround", "reverse"]
이는
from sound.effects import *
사운드 패키지의 3 개의 명명 된 하위 모듈을 가져 오는 것을 의미 합니다.
사용하여 importlib
추가 할 수있어 유일한 것입니다
from importlib import import_module
from pathlib import Path
__all__ = [
import_module(f".{f.stem}", __package__)
for f in Path(__file__).parent.glob("*.py")
if "__" not in f.stem
]
del import_module, Path
error: Type of __all__ must be "Sequence[str]", not "List[Module]"
합니다. __all__
이 import_module
기반 접근법을 사용 하는 경우 정의 가 필요하지 않습니다 .
표준 라이브러리에서 pkgutil 모듈을보십시오. __init__.py
디렉토리에 파일 이 있으면 원하는 것을 정확하게 수행 할 수 있습니다 . __init__.py
파일이 비어있을 수 있습니다.
이를 위해 모듈을 만들었습니다.이 모듈은 __init__.py
다른 보조 파일 에 의존하지 않고 다음 두 줄만 입력하게합니다.
import importdir
importdir.do("Foo", globals())
http://gitlab.com/aurelien-lourot/importdir : 자유롭게 재사용하거나 기여하십시오.
importlib로 가져 와서 패키지 에 반복적 으로 추가하십시오 __all__
( add
작업은 선택 사항입니다) __init__.py
.
/Foo
bar.py
spam.py
eggs.py
__init__.py
# __init__.py
import os
import importlib
pyfile_extes = ['py', ]
__all__ = [importlib.import_module('.%s' % filename, __package__) for filename in [os.path.splitext(i)[0] for i in os.listdir(os.path.dirname(__file__)) if os.path.splitext(i)[1] in pyfile_extes] if not filename.startswith('__')]
del os, importlib, pyfile_extes
py
때 from . import *
충분히 좋은이 아닌, 이것은 비해 개선 테드 의해 답변 . 특히, __all__
이 접근 방식의 사용이 필요하지 않습니다.
"""Import all modules that exist in the current directory."""
# Ref https://stackoverflow.com/a/60861023/
from importlib import import_module
from pathlib import Path
for f in Path(__file__).parent.glob("*.py"):
module_name = f.stem
if (not module_name.startswith("_")) and (module_name not in globals()):
import_module(f".{module_name}", __package__)
del f, module_name
del import_module, Path
module_name not in globals()
주기적으로 반입 될 위험이 있으므로 이미 반입 된 모듈을 다시 반입하지 않도록 주의하십시오 .