python 功能使用技巧_包管理_系统搭建_conda_import

1. 虚拟环境机理

在 Conda 环境中,activate.d 目录用于存放当激活环境时自动执行的脚本。这些脚本可以是 shell 脚本(如 .sh 文件)或批处理脚本(如 .bat 文件),具体取决于你的操作系统。

cd ~/anaconda3/envs/myenv/etc/conda/activate.d

Conda 环境的激活过程通常会执行 activate.d 目录下的所有脚本,然后,每次激活该 Conda 环境时,你的自定义脚本就会被执行。

gdp@gdp:~/anaconda3/envs/myenv/etc/conda/activate.d$ ls
libglib_activate.sh  qt-main_activate.sh 

可以自己添加一个脚本文件env_vars.sh,内容为:

export LD_LIBRARY_PATH=~/anaconda3/envs/myenv/lib:$LD_LIBRARY_PATH

添加了路径依赖

2. 当前工作目录 和 Python模块导入机制

有时python的site-packages下面的包导出不成功/home/gdp/anaconda3/envs/myenv/lib/python3.8/site-packages/fbx/,切换到cd ..目录下,可以import,但是内容是空的。

Python的模块搜索路径 (sys.path)

当你在 site-packages/fbx 目录下直接运行 Python 时,当前目录 (~/anaconda3/envs/myenv/lib/python3.8/site-packages/fbx) 会被自动添加到 sys.path 的最前面。日常可以显式指定模块路径,在代码中手动调整 sys.path

import sys
# 确保 site-packages 路径在 sys.path 中,且优先级高于当前目录
sys.path.insert(0, "/home/gdp/anaconda3/envs/myenv/lib/python3.8/site-packages")

from fbx import *  # 此时应正常导入

检查 fbx 包安装完整性

fbx 模块的安装目录包含FbxCommon.py  fbxsip.so  fbx.so文件,通常应包含 __init__.py 文件

  • __init__.py 的核心功能
    定义包的初始化逻辑,控制模块的导入行为。此处需要实现:

    1. 确保 fbx.so 和 fbxsip.so 能够正确加载。

    2. 暴露 FbxCommon.py 中的工具函数或类。

    3. 解决路径冲突问题(避免因当前目录干扰模块搜索)。

__init__.py文件内容,一般如下,从*.so库中导入文件,这样导入后,模块内容就不会是空的

*.so文件可以直接from 文件名 import *

# ~/anaconda3/envs/myenv/lib/python3.8/site-packages/fbx/__init__.py
import sys
import os

# 确保优先从当前包的目录加载模块(避免同名模块冲突)
_package_dir = os.path.dirname(__file__)
if _package_dir in sys.path:
    sys.path.remove(_package_dir)
sys.path.insert(0, os.path.dirname(_package_dir))  # 确保父目录在路径中

# 导入核心模块
from .fbx import *          # 导入 fbx.so 的所有符号
from .fbxsip import *        # 导入 fbxsip.so 的所有符号

# 导入辅助工具模块(可选)
from .FbxCommon import *     # 导入 FbxCommon.py 的所有工具函数/类

# 清理临时变量(可选)
del sys, os, _package_dir

3. 运行找不到依赖

例如:from .fbx import * # 导入 fbx.so 的所有符号 ImportError: /home/gdp/anaconda3/envs/myenv/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /home/gdp/anaconda3/envs/myenv/lib/python3.8/site-packages/fbx/fbx.so)

根据错误信息,fbx.so 需要 GLIBCXX_3.4.30,但当前 Anaconda 环境中的 libstdc++.so.6 不包含此版本

1. 升级 Conda 环境中的 libstdcxx-ng

在 Conda 环境中安装或更新 libstdcxx-ng(包含较新的 libstdc++.so.6):

# 激活环境
conda activate myenv

# 更新 libstdcxx-ng(指定版本)
conda install -c conda-forge libstdcxx-ng=11 -y
2. 验证 GLIBCXX 版本

检查当前环境中的 libstdc++.so.6 是否包含 GLIBCXX_3.4.30

# 查看支持的 GLIBCXX 版本
strings ~/anaconda3/envs/myenv/lib/libstdc++.so.6 | grep GLIBCXX

# 输出应包含以下内容:
GLIBCXX_3.4.30
GLIBCXX_3.4.31
...

Conda 环境中的 libstdc++ 版本已无法满足,系统安装的 GCC 11+),可以绕过 Conda 的旧版本库

查找系统的 libstdc++.so.6
# 查找系统库路径
find /usr -name "libstdc++.so.6" 2>/dev/null
# 典型路径:/usr/lib/x86_64-linux-gnu/libstdc++.so.6

# 检查是否包含 GLIBCXX_3.4.30
strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX_3.4.30
替换 Conda 环境的库文件
# 备份旧库
mv $CONDA_PREFIX/lib/libstdc++.so.6 $CONDA_PREFIX/lib/libstdc++.so.6.bak

# 创建符号链接指向系统库
ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 $CONDA_PREFIX/lib/libstdc++.so.6

4. .egg-link 文件, Python 的「开发模式安装」,pip install -e .

当用 pip install -e . 安装包时:

  1. 不复制代码到 site-packages,而是创建一个 .egg-link 文本文件

  2. 文件内容记录了你项目的绝对路径(如 /home/user/my_project

  3. Python 解释器导入包时,会通过这个文件「跳转」到你的项目目录读取代码

例子

  1. 你的项目结构:

    my_project/
    ├── setup.py
    └── my_package/
    └── __init__.py # 里面写了个 print("Hello!")
  2. 执行 pip install -e . 后,site-packages 中会出现:

    my_package.egg-link # 内容:/home/user/my_project
  3. 此时在任意位置运行 Python:

    python
    import my_package # 会直接读取 /home/user/my_project/my_package 下的代码
  4. 修改 __init__.py 为 print("Hi!"),无需重新安装,再次导入就会生效

  • 还会生成 easy-install.pth 文件,记录所有通过 -e 模式安装的包
  • 删除 .egg-link 和 .pth 中的对应条目,相当于「取消直播」
  • 生产环境不要用 -e 模式,因为路径依赖可能导致环境不一致

5. 模块导入的绝对导入和相对导入

核心规则总结

1. 运行文件(Top-level Script)

  • 必须使用绝对导入:直接执行的脚本(如 python main.py)中,若使用相对导入会报错。

  • 原因:直接运行时,Python 将文件视为顶层模块(__name__ = "__main__"),无法识别包层级结构

2. 包内模块(Package Modules)
  • 推荐使用相对导入:包内部的子模块相互引用时,优先使用相对导入(如 from . import module)。

  • 优势:避免硬编码包名,提升代码可维护性(包名变更时无需修改导入路径)

解释

绝对导入: 从项目根目录(顶层包)开始的完整路径导入。

from myapp.utils.logger import setup_logger  # 根目录为 myapp

  • 适用场景:顶层脚本(如 main.py),跨包引用(如从 app/core 导入 app/utils 的模块),引用第三方库(如 from flask import Flas

相对导入(Relative Import):

  • 只能在包内模块中使用,不可用于顶层脚本710。

  • 需通过 python -m package.module 运行(确保包结构被识别)

Tips: 优先使用绝对导入,尤其在大型项目中。包内模块使用相对导入,简化包内引用,避免硬编码包名。统一运行方式,包内模块通过 python -m 运行,确保包结构被正确识别。配置项目路径,若需跨包导入,可将根目录加入 sys.path

6. 在 sys.path 中添加项目根目录,实现跨包导入

问题描述:

my_project/
├── src/
│   ├── utils/
│   │   ├── math_tools.py   # 包含数学工具函数
│   │   └── __init__.py
│   ├── models/
│   │   ├── user.py         # 需要调用 math_tools
│   │   └── __init__.py
│   └── main.py            # 主入口文件
└── requirements.txt

在 user.py 中想调用 math_tools.py 的函数:

# src/models/user.py
from utils.math_tools import calculate_discount  # ❌ 错误:无法找到 utils 模块

def process_user():
    discount = calculate_discount(100, 0.2)
    print(f"折扣金额: {discount}")

解决方案:在入口文件添加根目录路径

# src/main.py
import os
import sys

# 关键代码:获取项目根目录路径并添加到 sys.path
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(project_root)  # ✅ 现在可以找到所有子模块

# 然后导入其他模块
from models.user import process_user

if __name__ == "__main__":
    process_user()

然后, user.py无需修改即可运行

# 在项目根目录执行
cd my_project
python src/main.py

原理解释:

  1. __file__:获取当前文件路径(main.py 的路径)

  2. os.path.abspath(__file__):转为绝对路径(如 /home/user/my_project/src/main.py

  3. os.path.dirname()

    • 第一次:得到 /home/user/my_project/src

    • 第二次:得到 /home/user/my_project(项目根目录)

  4. sys.path.append():将此路径/home/user/my_project加入 Python 的模块搜索路径,python会去按照名称搜索需要的模块。

7. 在 VSCode 中实现 MATLAB 风格的 Python 调试

如何使用vscode调试python代码,使得使用方法和matlab一样。即:可以一行一行的运行代码,运行后,可以在界面上查看变量的内容,运行结束变量内容不清零,保留在VARIABLE窗口中,最好运行后,可以自动打印变量的内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值