python相对路径导包|模块

部署运行你感兴趣的模型镜像

https://www.cnblogs.com/f-ck-need-u/p/9961372.html#%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84%E5%AF%BC%E5%85%A5%E9%99%B7%E9%98%B1

例如 "from .. import m0718"或"from . import m0718_temp"会提示在"父包未知时尝试相关导入"

这是因为:python导包和导模块路径为sys.path和脚本所在目录,在python3.8中是先在脚本所在目录查找,查找不到时再从左至右在sys.path的目录列表中查找,打印sys.path的第一个''就表示脚本所在目录。形如"$ python3.8 m07182.py"这样的调用,Python解释器在cd的pwd目录中执行m07182.py模块,此时m07182.py是一个模块而不是一个包,没有包路径的概念,用户理解的上层目录".."或当前目录".",并不能被python解释器理解为"包的相对路径"。

解决方法:1、不使用".."或"."的相对路径表示,将要导入的模块或包的路径加到sys.path或放到sys.path的任何一个目录下;

2、形如"$ python3.8 -m ~/Files/pack/m07184.py"执行脚本文件,显式地带父目录或祖目录来执行一个模块,使python解释器获悉包路径,然后使用相对路径就可以被python解释器解析出绝对路径予以导入

3、具体原理以后再学习,这里先给出拙见

目录结构为

                      /home/haypin/Files/m0718.py                                        被调脚本

                      /home/haypin/Files/pack/m0718_temp.py               被调脚本

                      /home/haypin/Files/pack/m07182.py                          主调脚本

                      /home/haypin/Files/pack/m07184.py                          主调脚本

                      /home/haypin/Files/pack/subpack/m07185.py       被调脚本

可以看到,第一种方式cd 到主调脚本m07182.py所在目录~/Files/pack,print(__file__)只打印相对pwd目录下的文件名,print(__package__)则打印None,说明只把m07182.py当做模块而不是包,不是包就没有路径,不能用".."或"."表示父目录或当前目录,因为没法解析。

第二种方式cd到主调脚本和被调脚本共同的父目录或祖目录,然后以包的形式调用主调脚本模块,此时print(__file__)会打印出主调脚本的绝对路径,并不是相对于pwd的相对路径,print(__package__)打印"Files.pack"的包路径,"pack"是主调脚本模块的当前目录".","Files"是主调脚本模块的父目录"..",此时python解释器能将".."与"."按照包路径解析成对应的父目录与"当前目录",从而可以执行相对路径导包。

如果是通过包导入的模块中有相对路径导入,则在导包时也要显式提供父包".."与当前包"."

通过祖包"..."的相对路径导入也一样:

同理,cd到祖目录并以包的方式执行主调模块,从而使python解释器获悉"祖目录.父目录.当前目录"的包路径,就可以使用相对路径导入祖目录下的模块。

 

子包的传递导入:

https://blog.youkuaiyun.com/weixin_38256474/article/details/81228492

单独导入包(package):单独import某个包名称时,不会导入该包中所包含的所有子模块。
c.py导入同级目录B包的子包B1包的b2模块,执行b2模块的print_b2()方法:
c.py代码

import B
B.B1.b2.print_b2()
运行c.py,会报错。

解决办法:
B/__init__.py代码

from . import B1#其中的.表示当前目录
B/B1/__init__.py代码

from . import b2
此时,执行c.py,成功打印:b2。

 

20200725补充:

学习Django源码时看到了builtin的/usr/lib/python3.8/importlib/__init__.py中定义的导包函数import_module(name, package=None):

def import_module(name, package=None):
    """Import a module.

    The 'package' argument is required when performing a relative import. It
    specifies the package to use as the anchor point from which to resolve the
    relative import to an absolute import.
    

    """
    '''导入一个模块,当执行相对导入时参数'package'会被用到,它指定了被用来作为锚点的包,
    该锚点用来分解相对导入为绝对导入。也就是说相对导入仍然需要包名来确定一个相对
    sys.path的绝对路径来进行导入,本质上也是绝对路径导入。
    '''
    level = 0
    if name.startswith('.'):
        if not package:
            msg = ("the 'package' argument is required to perform a relative "
                   "import for {!r}")
            raise TypeError(msg.format(name))
        for character in name:
            if character != '.':
                break
            level += 1
    return _bootstrap._gcd_import(name[level:], package, level)

importlib.import_module(name, package)的使用,这里包名package与模块名name都是字符串,并且模块名要自己带个'.',其实就相当于"import package.name",没这个点还不行

'''a temp module m0809'''
from sys import path
path.append('/home/haypin/Files')
import importlib
m08092 = importlib.import_module('.m08092','pack.subpack')
print(m08092)

python3.8执行输出:
execute pack/__init__.py successed!
execute pack/subpack/__init__.py successed!
<module 'pack.subpack.m08092' from '/home/haypin/Files/pack/subpack/m08092.py'>
haypin@ubt:~/Files$

 

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>我们讨论的是如何从文件Python模块。在Python中,我们可以通过多种方式从文件模块入整个模块入特定函数/类,或者通过相对入(在内)。以下将详细说明各种方法。 ### 1. 入整个模块 假设我们有一个名为 `utils.py` 的文件,内容如下: ```python # utils.py def greet(name): return f"Hello, {name}!" def add(a, b): return a + b ``` 在另一个文件中,我们可以这样入: ```python import utils print(utils.greet("Alice")) # 输出: Hello, Alice! print(utils.add(2, 3)) # 输出: 5 ``` ### 2. 入特定函数/类 从 `utils.py` 入特定函数: ```python from utils import greet, add print(greet("Bob")) # 直接使用函数名 print(add(5, 7)) ``` ### 3. 使用别名 当模块名或函数名较长或可能冲突时,可以使用别名: ```python import utils as u from utils import greet as hello print(u.add(10, 20)) print(hello("Charlie")) ``` ### 4. 从中的文件入 如果文件在中(即在一个目录中,且该目录含 `__init__.py` 文件),则可以使用点标记法。 假设目录结构如下: ``` my_package/ __init__.py utils.py math_tools.py ``` 在 `math_tools.py` 中,我们可以这样入同下的 `utils` 模块: ```python # my_package/math_tools.py from . import utils # 相对入 def multiply(a, b): return a * b def use_utils(): return utils.add(10, 20) * multiply(3, 4) ``` 在外部,我们可以这样入: ```python from my_package import utils from my_package.math_tools import multiply print(utils.greet("David")) print(multiply(4, 5)) ``` ### 5. 入文件中的所有内容(不推荐) 使用 `from module import *` 会模块中所有非下划线开头的名字。但这种方式可能致命名冲突,且可读性差。 ```python from utils import * print(greet("Eve")) print(add(10, 20)) ``` ### 6. 动态入(运行时入) 使用 `importlib` 模块可以在运行时动态入。 ```python import importlib module_name = "utils" utils = importlib.import_module(module_name) print(utils.greet("Frank")) ``` ### 注意事项 1. **搜索路径**:Python 会在 `sys.path` 中列出的目录中查找模块。当前目录通常在其中。 2. **避免循环入**:当两个模块相互入时会致循环入问题,应通过重构代码(例如将入放在函数内部)或使用接口模块来解决。 3. **重新加载模块**:使用 `importlib.reload(module)` 可以重新加载模块(在调试时有用),但通常不建议在生产环境中使用。 ### 示例:从当前目录下的文件入 假设当前目录结构: ``` project/ main.py helpers.py ``` 在 `main.py` 中: ```python import helpers helpers.say_hello() ``` 在 `helpers.py` 中: ```python def say_hello(): print("Hello from helpers!") ``` ### 示例:从子目录入 目录结构: ``` project/ main.py lib/ __init__.py helpers.py ``` 在 `main.py` 中: ```python from lib.helpers import say_hello say_hello() ``` 或者: ```python import lib.helpers lib.helpers.say_hello() ``` ### 总结 从文件模块Python程序组织代码的基础。根据模块的位置和入需求,可以选择绝对入、相对入(在内)或动态入。遵循PEP8规范,避免使用 `from ... import *`,并注意入顺序(标准库、第三方库、本地模块)以提高代码可读性。 §§相关问题§§: 1. 如何解决Python中的循环入问题? 2. Python中 `__init__.py` 文件的作用是什么? 3. 动态模块(如使用 `importlib`)有哪些应用场景? 4. 如何查看当前已入的模块列表?</think>### Python 从文件详解 在 Python 中,从文件模块主要有以下三种场景,每种场景都有特定的入语法和注意事项: #### 1. 入同级目录下的模块 ```python # 入整个模块 import module_name # 入特定函数/类 from module_name import function_name, ClassName # 入并重命名 import module_name as alias ``` #### 2. 入子目录中的模块入) ```python # 中的模块 from package_name import module_name # 模块中的特定对象 from package_name.module_name import function_name # 中子模块 from package_name.subpackage import module_name ``` #### 3. 入上级目录或任意路径的模块 ```python import sys import os # 添加父目录到系统路径 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # 现在可以入父目录中的模块 from parent_module import some_function ``` ### 关键注意事项 1. **`__init__.py` 文件的作用** - 在目录中必须含此文件(Python 3.3+ 后非必须,但推荐保留) - 用于初始化和定义 `__all__` 变量 - 示例: ```python # my_package/__init__.py __all__ = ['module1', 'module2'] # 控制 from package import * 的行为 ``` 2. **相对入(在内部使用)** ```python # 当前目录下的模块 from . import sibling_module # 上级目录中的模块 from .. import parent_module # 同级目录的子 from .subpackage import module ``` 3. **路径处理最佳实践** ```python import sys from pathlib import Path # 添加项目根目录到系统路径 sys.path.append(str(Path(__file__).parent.parent)) # 现在可以直接入项目根目录下的任何模块 from core.utils import helper_function ``` ### 常见错误及解决方法 **错误:ModuleNotFoundError** - 原因:Python 找不到模块路径 - 解决方案: ```python import sys print(sys.path) # 检查当前搜索路径 ``` **错误:ImportError: attempted relative import with no known parent package** - 原因:在非环境中使用相对入 - 解决方案: 1. 确保文件在结构中(有 `__init__.py`) 2. 使用绝对入替代相对入 3. 以模块方式运行脚本:`python -m my_package.module` ### 完整示例项目结构 ``` my_project/ ├── main.py ├── utils/ │ ├── __init__.py │ ├── math_tools.py │ └── string_utils.py └── core/ ├── __init__.py └── processor.py ``` **main.py 中的入示例** ```python # 入同级目录下的模块 from utils.math_tools import add, multiply # 入子目录中的模块 from core.processor import process_data # 入整个 import utils # 使用别名 from utils.string_utils import capitalize as cap result = add(3, 5) processed = process_data(result) print(cap("hello world")) ``` **math_tools.py 中的相对入** ```python # 入同中的其他模块 from .string_utils import format_number def add(a, b): return format_number(a + b) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值