首页 > 解决方案 > Python 从另一个文件导出的包的子模块导入

问题描述

imports.py包含:

import os as exported_os

foo.py包含:

from imports import exported_os
print(exported_os.path.devnull)    # works

from imports.exported_os.path import devnull    # doesn't

有没有办法使第二次导入工作?我尝试添加__path__imports.py摆弄它,但什么也得不到。

实际用例:osissome_library_version_nexported_osis some_library_version(我试图避免some_library_version_n跨不同文件的许多实例)。

标签: pythonpython-3.xpython-importpython-packaging

解决方案


一种方法

目录结构:

__init__.py
foo.py
imports/
 ├ __init__.py
 └ exported_os/
    ├ __init__.py
    └ path.py

imports/exported_os/__init__.py

from . import path
from os import *  # not necessary for the question 
                  # but it makes `exported_os` more like `os`
                  # e.g., `exported_os.listdir` will be callable

imports/exported_os/path.py

from os.path import *

这样,您可以像使用子模块exported_os一样使用它。与 不同,采用模块和类。ospathimportfrom

另一种方法

imports.py

import os
import sys

ms = []
for m in sys.modules:
    if m.startswith('os'):
        ms.append(m)

for m in ms:
    sys.modules['imports.exported_os' + m[2:]] = sys.modules[m]

或者,通过显式扩展,sys.modules您可以exported_osos使用它的子模块一样使用。

为什么你不能简单地改变名字os

如果你打开.../lib/python3.9/os.py你可以找到以下行:

sys.modules['os.path'] = path

因此,即使您复制.../lib/python3.9/os.py.../lib/python3.9/exported_os.py,以下内容也不起作用:

from exported_os.path import devnull

但是,如果您将线路更改为sys.modules['os.path']有效sys.modules['exported_os.path']


推荐阅读