欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文教你如何解決Python開(kāi)發(fā)總是import出錯(cuò)的問(wèn)題

 更新時(shí)間:2025年05月09日 16:24:38   作者:田辛 | 田豆芽  
經(jīng)常朋友碰到Python開(kāi)發(fā)的過(guò)程中import包報(bào)錯(cuò)的問(wèn)題,所以本文將和大家介紹一下可編輯安裝(Editable Install)模式,可以輕松解決import出錯(cuò)的問(wèn)題,感興趣的可以了解下

摘要

有很多朋友碰到開(kāi)發(fā)的過(guò)程中import包報(bào)錯(cuò)的問(wèn)題。今天想介紹一個(gè)可編輯安裝(Editable Install)模式, 方便快捷的解決這個(gè)問(wèn)題。讓開(kāi)發(fā)者的思路集中在業(yè)務(wù)的實(shí)現(xiàn)上。

1. 可編輯安裝(Editable Install)模式到底在解決什么問(wèn)題?

在 Python 開(kāi)發(fā)中,我們經(jīng)常需要修改本地包的代碼并實(shí)時(shí)測(cè)試效果。 而包這個(gè)概念可以說(shuō)在Python開(kāi)發(fā)中無(wú)處不在。 幾乎每天都要修改, 總不能每個(gè)包都重新反復(fù)的安裝吧。

可編輯安裝(Editable Install)模式正是為解決這一痛點(diǎn)而生,它允許開(kāi)發(fā)者在無(wú)需重新安裝的情況下直接運(yùn)行本地修改后的代碼。

2. 原理

可編輯安裝的本質(zhì)是通過(guò)符號(hào)鏈接(Symbolic Link)將包的源代碼目錄與 Python 環(huán)境中的包路徑關(guān)聯(lián)。當(dāng)執(zhí)行 pip install -e . 時(shí):

  • 創(chuàng)建鏈接:在系統(tǒng)目錄(如 site-packages)生成一個(gè)指向本地源碼目錄的符號(hào)鏈接。
  • 動(dòng)態(tài)加載:Python 導(dǎo)入包時(shí),實(shí)際加載的是源碼目錄中的文件,修改后立即生效。
  • 依賴(lài)隔離:包的依賴(lài)仍通過(guò) requirements.txt 或 pyproject.toml 管理,確保環(huán)境一致性。

3. 最簡(jiǎn)單的配置

3.1. 傳統(tǒng)項(xiàng)目(setup.py)

# 初始化項(xiàng)目結(jié)構(gòu)
mkdir my_package && cd my_package
touch setup.py  # 包含包元數(shù)據(jù)(名稱(chēng)、版本、依賴(lài)等)

# 安裝可編輯模式
pip install -e .

3.2. 現(xiàn)代項(xiàng)目(pyproject.toml)

# pyproject.toml 示例
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "my_package"
version = "0.1.0"
dependencies = ["requests>=2.25"]
# 使用 PEP 660 標(biāo)準(zhǔn)安裝
pip install -e .

4. 實(shí)際項(xiàng)目配置

4.1. 本次項(xiàng)目結(jié)構(gòu)

本次項(xiàng)目,是針對(duì)各種AI功能的研究。 希望是通過(guò)統(tǒng)一項(xiàng)目結(jié)構(gòu)便于小朋友發(fā)揮想象開(kāi)發(fā)有趣的功能。

環(huán)境管理使用Conda

PROJECT_ROOT
├─bin                # 可執(zhí)行文件/Shell/Batch
│ ├─ run.bat        # 啟動(dòng)streamlit服務(wù)
│ ├─ install.py        # `Editable Install` 安裝自動(dòng)化腳本
│ └─ uninstall.py    # `Editable Install` 卸載自動(dòng)化腳本
├─config
├─docs                # 項(xiàng)目文檔
├─input                # 輸入文件
├─logs                # 日志文件
├─output            # 輸出文件
├─reports            # 報(bào)告文件
├─resource            # 資源文件
│  ├─image
│  └─excel
├─src                # 項(xiàng)目代碼,遵循PEP 517/518標(biāo)準(zhǔn)
│  ├─tdouya_ai_assistant
│  ├─aliyun            # 阿里云相關(guān)功能包
│  ├─basic            
│  ├─common
│  │  └─log_record  # 日志記錄功能
│  ├─game            # 基于AI的游戲
│  ├─interface
│  │  └─pages       
│  ├─ollama
│  ├─siliconflow
│  ├─tools            # 工具封裝的包
│  └─volcengine
└─tests                # 測(cè)試代碼

在這個(gè)項(xiàng)目中, 作為共通部分的common/log_record必然會(huì)被其他部分調(diào)用

4.2 創(chuàng)建必須的環(huán)境文件

4.2.1 pyproject.toml

在Python生態(tài)不斷演進(jìn)的今天,pyproject.toml已成為現(xiàn)代項(xiàng)目不可或缺的配置中樞。這個(gè)遵循TOML語(yǔ)法的文件不僅統(tǒng)一了構(gòu)建流程,更重塑了依賴(lài)管理和項(xiàng)目元數(shù)據(jù)的配置方式。本文將結(jié)合最新實(shí)踐,為您深度解析這個(gè)配置文件的架構(gòu)與應(yīng)用。

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "Tdouya-AI-Assistant"          # ?? 用戶(hù)指定項(xiàng)目名稱(chēng)
version = "0.1.1"
authors = [{name = "田辛老師", email = "tianxin.xp@gmail.com"}]  # ?? 用戶(hù)信息
description = "基于AI的智能助手開(kāi)發(fā)框架"
readme = "README.md"
requires-python = ">=3.12"

[tool.setuptools]
package-dir = { "" = "src" }  # 聲明包根目錄在src下

這里面比較重要的設(shè)定是最后一句:生命包的根目錄在src目錄下。 另外,這個(gè)文件中項(xiàng)目名必須為英文,中文親測(cè)不行。

4.2.2 setup.py

在Python生態(tài)中,setup.py曾是項(xiàng)目打包分發(fā)的標(biāo)準(zhǔn)配置文件,承載著將代碼轉(zhuǎn)化為可安裝包的使命。盡管現(xiàn)代工具鏈已轉(zhuǎn)向pyproject.toml,但理解這個(gè)經(jīng)典文件仍是掌握Python打包歷史的必修課。

from setuptools import setup, find_packages

setup(
    name="Tdouya-AI-Assistant",  # ?? 必須與pyproject.toml一致
    version="0.1.1",
    author="田辛老師",
    author_email="tianxin.xp@gmail.com",
    description="基于AI的智能助手開(kāi)發(fā)框架",
    packages=find_packages(where="src"),  # 指定包搜索路徑
    package_dir={"": "src"},  # 聲明包根目錄
    install_requires=[
        "python-dotenv>=0.19.0", 
        "requests>=2.21.0",  
        "streamlit>=1.0.0", 
        "moviepy>=1.0.3",  
        "colorlog>=6.7.0",
        "langchain_ollama",
        "langchain_core",
        "langchain_community",
        "ollama",
        "dashscope"
    ],
    python_requires=">=3.12",
)

這樣做的目的是,

  • 標(biāo)準(zhǔn)化項(xiàng)目元數(shù)據(jù)(名稱(chēng)、版本、作者等)
  • 聲明Python版本要求
  • 定義包結(jié)構(gòu)和依賴(lài)關(guān)系
  • 兼容現(xiàn)代構(gòu)建工具(poetry/flit)和傳統(tǒng)setuptools

4.2.3. 創(chuàng)建__init__.py文件

在各個(gè)模塊的目錄下, 創(chuàng)建__init__.py文件。
這個(gè)文件如何使用, 在我開(kāi)始提到的文件中詳細(xì)介紹過(guò)。 在Python開(kāi)發(fā)中非常靈活, 比如,我之前提到封裝的log_record包就把所有的代碼放到__init__.py中了

4.2.4. 執(zhí)行可編輯安裝

在命令行中執(zhí)行:

pip install -e .

這樣做可以實(shí)現(xiàn)目標(biāo):

  • 將項(xiàng)目注冊(cè)為開(kāi)發(fā)模式包
  • 建立符號(hào)鏈接到Conda環(huán)境的site-packages
  • 實(shí)現(xiàn)代碼修改即時(shí)生效

這樣做的結(jié)果是在src目錄下生成了一個(gè)符號(hào)鏈接的文件夾,如下圖。

內(nèi)容完全不用管, 只需要把這個(gè)文件放到Git忽略文件即可。

執(zhí)行完成后, 可以通過(guò)下面的方式測(cè)試一下:

PS E:\BG10-TRN-AIT-AI編程> python -c "import tdouya_ai_assistant; print(f'項(xiàng)目版本: {tdouya_ai_assistant}')"            
項(xiàng)目版本: <module 'tdouya_ai_assistant' from 'E:\\BG10-TRN-AIT-AI編程\\src\\tdouya_ai_assistant\\__init__.py'>

5. 自動(dòng)化

pip install -e . 這個(gè)寫(xiě)法,加上卸載的命令, 實(shí)在是太容易忘了, 尤其是對(duì)新人來(lái)說(shuō), 于是貼心的給他們寫(xiě)了一個(gè)安裝腳本,一個(gè)卸載腳本。主要的邏輯是, 找到項(xiàng)目根目錄, 然后將根目錄作為工作目錄執(zhí)行:

  • 安裝 pip install -e .
  • 卸載 pip uninstall -y Tdouya-AI-Assistant

兩個(gè)文件的源代碼田老師已經(jīng)給到大家了, 請(qǐng)參考:

5.1. 安裝腳本

# ==============================================
# 文件名: init.py
# 描述: 此腳本用于查找項(xiàng)目根路徑,若項(xiàng)目未初始化則進(jìn)行初始化操作,已初始化則給出提示。
# 作者: 田辛
# 創(chuàng)建日期: 2025-05-07
# ==============================================
# 導(dǎo)入操作系統(tǒng)相關(guān)功能模塊,用于文件和目錄操作
import os

# 導(dǎo)入子進(jìn)程模塊,用于創(chuàng)建新進(jìn)程執(zhí)行外部命令
import subprocess

# 導(dǎo)入系統(tǒng)相關(guān)功能模塊,用于獲取Python解釋器信息
import sys

# 導(dǎo)入日期時(shí)間模塊,用于獲取當(dāng)前時(shí)間
import datetime

# 獲取當(dāng)前腳本所在的絕對(duì)路徑目錄
script_dir = os.path.dirname(os.path.abspath(__file__))
# 初始化當(dāng)前搜索目錄為腳本所在目錄
current_dir = script_dir

while True:
    # 定義項(xiàng)目已初始化時(shí)所需的文件列表
    required_files = [
        "setup.py",
        "pyproject.toml",
        "README.md",
        "CONTRIBUTING.md",
        "installed.lock",
    ]
    # 檢查當(dāng)前目錄是否存在所有已初始化所需的文件
    if all(os.path.isfile(os.path.join(current_dir, f)) for f in required_files):
        print(
            f"田豆芽AI助手已安裝, 若想再次安裝請(qǐng)先卸載。卸載命令:python {script_dir}/uninstall.py"
        )
        break
    # 定義項(xiàng)目未初始化時(shí)所需的文件列表
    original_required_files = [
        "setup.py",
        "pyproject.toml",
        "README.md",
        "CONTRIBUTING.md",
    ]
    # 檢查當(dāng)前目錄是否存在所有未初始化所需的文件
    if all(
        os.path.isfile(os.path.join(current_dir, f)) for f in original_required_files
    ):
        try:
            # 切換當(dāng)前工作目錄到項(xiàng)目根路徑
            os.chdir(current_dir)
            # 使用當(dāng)前Python解釋器執(zhí)行 `pip install -e .` 命令進(jìn)行項(xiàng)目安裝
            result = subprocess.run(
                [sys.executable, "-m", "pip", "install", "-e", "."],
                capture_output=True,
                text=True,
                check=True,
            )
            print(result.stdout)
            # 生成鎖定文件路徑
            lock_file_path = os.path.join(current_dir, "installed.lock")
            # 打開(kāi)鎖定文件并寫(xiě)入當(dāng)前時(shí)間戳
            with open(lock_file_path, "w") as f:
                f.write(datetime.datetime.now().strftime("%Y%m%d %H:%M:%S"))
            print(f"田豆芽AI助手安裝完成。")
        except subprocess.CalledProcessError as e:
            # 捕獲子進(jìn)程執(zhí)行錯(cuò)誤并輸出錯(cuò)誤信息
            print(f"執(zhí)行 `pip install -e .` 命令時(shí)出錯(cuò): {e.stderr}")
        except Exception as e:
            # 捕獲其他異常并輸出錯(cuò)誤信息
            print(f"執(zhí)行命令時(shí)出錯(cuò): {e}")
        break
    else:
        # 獲取當(dāng)前目錄的上一級(jí)目錄
        new_dir = os.path.dirname(current_dir)
        # 檢查是否已經(jīng)回到根驅(qū)動(dòng)器,如果是則表示未找到項(xiàng)目根路徑
        if new_dir == current_dir[:3]:
            print("未找到項(xiàng)目根路徑。")
            break
        # 更新當(dāng)前搜索目錄為上一級(jí)目錄
        current_dir = new_dir

5.2. 卸載腳本

# ==============================================
# 文件名: uninstall.py
# 描述: 此腳本用于查找項(xiàng)目根路徑,執(zhí)行卸載操作并刪除鎖定文件。
# 作者: 田辛
# 創(chuàng)建日期: 2025-05-07
# ==============================================
import os
import subprocess
import sys

# 獲取當(dāng)前腳本所在的絕對(duì)路徑目錄
script_dir = os.path.dirname(os.path.abspath(__file__))
# 初始化當(dāng)前搜索目錄為腳本所在目錄
current_dir = script_dir

while True:
    # 定義項(xiàng)目已初始化時(shí)所需的文件列表
    required_files = [
        "setup.py",
        "pyproject.toml",
        "README.md",
        "CONTRIBUTING.md",
        "installed.lock",
    ]
    # 檢查當(dāng)前目錄是否存在所有已初始化所需的文件
    if all(os.path.isfile(os.path.join(current_dir, f)) for f in required_files):
        try:
            # 切換當(dāng)前工作目錄到項(xiàng)目根路徑
            os.chdir(current_dir)
            # 執(zhí)行pip uninstall命令
            result = subprocess.run(
                [sys.executable, "-m", "pip", "uninstall", "-y", "Tdouya-AI-Assistant"],
                capture_output=True,
                text=True,
                check=True,
            )
            print(result.stdout)
            # 刪除鎖定文件
            lock_file_path = os.path.join(current_dir, "installed.lock")
            if os.path.isfile(lock_file_path):
                os.remove(lock_file_path)

            print("田豆芽AI助手卸載成功。")
        except subprocess.CalledProcessError as e:
            # 捕獲子進(jìn)程執(zhí)行錯(cuò)誤并輸出錯(cuò)誤信息
            print(f"執(zhí)行 `pip uninstall Tdouya-AI-Assistant` 命令時(shí)出錯(cuò): {e.stderr}")
        except Exception as e:
            # 捕獲其他異常并輸出錯(cuò)誤信息
            print(f"執(zhí)行命令時(shí)出錯(cuò): {e}")
        break
    else:
        # 獲取當(dāng)前目錄的上一級(jí)目錄
        new_dir = os.path.dirname(current_dir)
        # 檢查是否已經(jīng)回到根驅(qū)動(dòng)器,如果是則表示未找到項(xiàng)目根路徑
        if new_dir == current_dir[:3]:
            print("未找到項(xiàng)目根路徑。")
            break
        # 更新當(dāng)前搜索目錄為上一級(jí)目錄
        current_dir = new_dir

6. 總結(jié)與展望:讓開(kāi)發(fā)回歸創(chuàng)造本身

通過(guò)可編輯安裝模式,我們成功將Python開(kāi)發(fā)體驗(yàn)提升到新維度。這種模式帶來(lái)的不僅是「修改即生效」的技術(shù)便利,更是開(kāi)發(fā)思維的解放——開(kāi)發(fā)者無(wú)需再為包管理分心,可全身心投入業(yè)務(wù)邏輯的創(chuàng)新。

6.1 核心價(jià)值重述

效率革命:告別pip install的等待循環(huán),代碼修改秒級(jí)生效

環(huán)境穩(wěn)定:符號(hào)鏈接機(jī)制保障開(kāi)發(fā)環(huán)境與生產(chǎn)環(huán)境的高度一致性

架構(gòu)自由:平級(jí)模塊間自由引用,支持微服務(wù)化開(kāi)發(fā)范式

流程標(biāo)準(zhǔn)化:通過(guò)pyproject.toml+setup.py雙配置實(shí)現(xiàn)現(xiàn)代與傳統(tǒng)項(xiàng)目的兼容

6.2 最佳實(shí)踐建議

版本控制:將installed.lock文件納入Git管理,避免重復(fù)安裝

環(huán)境隔離:為每個(gè)項(xiàng)目創(chuàng)建獨(dú)立Conda環(huán)境,防止依賴(lài)污染

自動(dòng)化升級(jí):定期執(zhí)行pip list --outdated檢查依賴(lài)更新

跨平臺(tái)適配:Windows用戶(hù)需確認(rèn)符號(hào)鏈接權(quán)限(需開(kāi)啟Developer Mode)

6.3 未來(lái)演進(jìn)方向

隨著Python打包工具鏈的持續(xù)演進(jìn),可編輯安裝模式正呈現(xiàn)三大趨勢(shì):

  • 與IDE深度集成:PyCharm/VSCode已原生支持開(kāi)發(fā)模式包提示
  • 容器化適配:在Docker開(kāi)發(fā)環(huán)境中實(shí)現(xiàn)熱重載(需結(jié)合volume掛載)
  • AI輔助調(diào)試:未來(lái)可能通過(guò)LLM自動(dòng)分析循環(huán)依賴(lài)問(wèn)題

到此這篇關(guān)于一文教你如何解決Python開(kāi)發(fā)總是import出錯(cuò)的問(wèn)題的文章就介紹到這了,更多相關(guān)Python解決import出錯(cuò)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論