包 __init__.py 导入所有子文件,但只从另一个脚本加载一个? [英] Package __init__.py import all subfiles, but only load one from another script?
问题描述
我创建了一个具有以下文件结构的包:
I have created a package with the following file structure:
- package
- __init__.py
- load.py
- train.py
- test.py
我的 __init__.py
文件只是这些文件的类的导入:
My __init__.py
file is simply an import of classes for these files:
from package.load import Load
from package.train import Train
from package.test import Test
大多数时候,我想加载所有三个类,但有时我只想专门加载这些类中的一个.例如,在一个临时脚本(包外)中,我希望能够像这样只调用 Load 类:
Most of the time, I want to load all three, however on occasion I only want to load one of these classes specifically. For example in an ad hoc script (outside of the package) I want to be able to call only the Load class like so:
from package import Load
虽然上述所有内容都在此设计中有效,但我遇到了一个问题,即当我像上面那样导入 Load
时,也会加载来自 train/test 的依赖项.如何设置 __init__.py
文件,以便我可以进行相同的 import
调用而无需从训练/测试加载依赖项?
While all of the above works in this design, I have an issue where dependencies from train/test are also loaded when I import Load
like the above. How can I setup the __init__.py
file such that I can make the same import
call without getting the dependency to load from train/test?
补充说明:
我为什么要这样做:我有一个问题,我希望某些人能够使用 Load
类,该类只使用基础 Python,但是训练/测试文件包含专门的依赖项只使用 Load 类的用户不会想要使用甚至安装.
Why I am doing this: I have an issue where I want some people to be able to use the Load
class, which only uses base python, however the Train/Test files include specialized dependencies which users of just the Load class wont want to utilize or even install.
推荐答案
这里有一种方法可以做一些非常接近你想要的事情.与其无条件地import
__init__.py
中的所有包类,您可以在其中定义一个函数来显式导入任何所需的类(或所有这些类,如果没有指定).
Here's a way to do something very close what you want. Instead of unconditionally import
ing all the package's classes in your __init__.py
, you can define a function in it to explicitly import any of the ones desired (or all of them if none are specified).
__init__.py
:
from pathlib import Path
import sys
print(f'In {Path(__file__).name}')
package_name = Path(__file__).parent.name
package_prefix = package_name + '.'
class_to_module_map = {'Load': 'load', 'Train': 'train', 'Test': 'test'}
def import_classes(*class_names):
namespace = sys._getframe(1).f_globals # Caller's globals.
if not class_names:
class_names = class_to_module_map.keys() # Import them all.
for class_name in class_names:
module = class_to_module_map[class_name]
temp = __import__(package_prefix+module, globals(), locals(), [class_name])
namespace[class_name] = getattr(temp, class_name) # Add to caller's namespace.
出于测试目的,以下是我在 load.py
脚本中添加的内容:
(我还在其他两个模块中放置了类似的东西,以验证它们是否被 import
ed.)
For testing purposes, here's what I put in the load.py
script:
(I also put something similar in the other two modules in order to verify whether or not they were getting import
ed.)
load.py
:
from pathlib import Path
print(f'In {Path(__file__).name}')
class Load: pass
最后这是一个使用它来仅import
Load
类的例子:
And finally here's a example of using it to only import
the Load
class:
ad_hoc.py
:
from my_package import import_classes
#from my_package import Load
import_classes('Load')
test = Load()
print(test)
连同产生的输出:
In __init__.py
In load.py
<my_package.load.Load object at 0x001FE4A8>
这篇关于包 __init__.py 导入所有子文件,但只从另一个脚本加载一个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!