包 __init__.py 导入所有子文件,但只从另一个脚本加载一个? [英] Package __init__.py import all subfiles, but only load one from another script?

查看:92
本文介绍了包 __init__.py 导入所有子文件,但只从另一个脚本加载一个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个具有以下文件结构的包:

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 importing 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 imported.)

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆