pip install -e .粗浅理解+白话分析
主要是记一下有关pip install -e .
的事情,一直没有理解清楚,ChatGPT也解释的很官方。直白来说这个命令是我在开发某一个库的时候使用的,可以让对代码的修改实时生效
为什么要有这个命令呢?其实是为了让正在开发的某个包的修改能够直接生效而无需重复安装。比如我在开发module1
,然后我在另一个项目 project1
(或者module1
项目中的测试代码)中使用到了module1
,按道理是此时的module1只是一段代码不是一个像torch, os
一样的包,是没法直接导入的。但这时候只需要在module1
那里 pip install -e .
后,首先把module1
当成了一个包装到了环境中,然后后续对module1
的改动都可以直接起作用而不用重新安装这个包。
pip install .
:安装后的模块freeze在pip/conda依赖下,换句话说,再修改本地的原项目文件,不会导致对应模块发生变化。
pip install -e .
:-e 理解为 editable,修改本地文件,调用的模块以最新文件为准。
**问题:**如果我在一个项目中开发包,同时又在这个项目中测试这个包,那不是完全没必要使用
pip install -e .
了吗?我直接就可以使用最新的代码呀。回答:
这是我自己提出的问题,其实很好回答,假设这个包叫
agent
,存在了项目根/src/agent
下。当没有用
pip install -e .
的时候,其实要开发的那个包就是这个项目中的一段寻常程序, 在测试代码的时候,我需要import src/agent/xxx
,这其实就是把那个包的文件当成了寻常的文件。但是
pip install -e .
后:在测试部分的代码中(测试代码不属于这个包),我可以from agent import xxx
,跟调用os
,datatime
等安装的包时的使用方式就完全一致了,把./src/agent
视为了一个可用的包而不是此项目下的简单程序。同时对于包里面程序,可以直接将agent
视为根来导入别的路径下的文件,即from agent import xxx
,与之相对的,不这样的话要从项目的根目录开始导入,即from src.agent import xxx
。而且这样对于相对路径导入包内别的程序也支持的更好的感觉。
问题:
pip install -e .
如何识别需要安装的库,比方说我测试和开发某个包是在同一个项目中,要如何区分与设置?**回答:**简单版:项目根目录下有一个
setup.py
负责控制具体如何安装包。后面是ChatGPT的回答:在执行
pip install -e .
时,它会查找当前目录中的setup.py
文件,并根据该文件中的配置来识别需要安装的库。通常情况下,setup.py
文件包含了一些元数据和依赖项信息,以告诉pip
如何安装您的包。对于测试和开发,您可以在
setup.py
文件中设置不同的依赖项,以区分测试和开发所需的库。以下是一些示例:from setuptools import setup, find_packages setup( name='my_package', version='0.1', packages=find_packages(), install_requires=[ 'numpy', # 生产环境和测试环境都需要的库 ], extras_require={ 'dev': ['pytest', 'flake8'], # 开发环境需要的库 'test': ['pytest'], # 测试环境需要的库 }, )
在这个示例中,
install_requires
参数指定了所有环境都需要安装的库,而extras_require
参数则允许您定义额外的依赖项,这些依赖项将根据您选择的环境进行安装。例如,当您使用pip install -e .[dev]
时,pytest
和flake8
将被安装;当您使用pip install -e .[test]
时,只会安装pytest
。您可以根据实际需要在
setup.py
文件中定义不同的依赖项和环境,以满足开发和测试的要求。然后,在执行pip install -e .
时,根据您的选择来安装适当的依赖项。
问题:
setup.py
中的package字段有什么作用?**回答:**简单版,就是用于告诉
pip install -e .
到底从哪里开始是那个正在开发的包。其实还可以设置package_dir
来指定包的位置(如果项目的路径很复杂的话)。下面是ChatGPT的回答:
packages
字段是 Python 中setuptools.setup()
函数的一个参数,用于指定哪些包应该包含在分发包中。在setup.py
文件中,packages
字段通常用于指定您的包的目录结构,以便打包和分发。它告诉 setuptools 应该包含哪些包及其子包。
packages
字段的值可以是一个字符串列表,也可以是一个包含字符串的列表,它们表示您的包的名称。如果您的包的目录结构非常简单,没有子包,您可以直接列出包的名称。例如:from setuptools import setup setup( name='my_package', version='0.1', packages=['my_package'], )
如果您的包包含多个子包,您可以使用
setuptools.find_packages()
函数来自动查找所有包。例如:from setuptools import setup, find_packages setup( name='my_package', version='0.1', packages=find_packages(), )
find_packages()
函数会递归地搜索当前目录及其子目录,并查找所有包。总的来说,
packages
字段的作用是告诉 setuptools 应该包含哪些包及其子包。根据您的包的目录结构,您可以手动指定包的名称,也可以使用find_packages()
函数来自动查找所有包。