是否可以在
setup.py
中指定已知驻留在本地文件系统上的(可编辑的)源依赖项?
考虑以下目录结构,所有这些都位于单个 VCS 存储库中:
projects
utils
setup.py
...
app1
setup.py
... # app1 files depend on ../utils
app2
setup.py
... # app2 files depend on ../utils
给出以下命令:
cd projects
mkvirtualenv app1
pip install -e app1
我想安装 app1 的所有依赖项,包括“utils”,这是一个“可编辑”依赖项。同样,如果我对 app2 做同样的事情。
我尝试过使用
file://...
和 install_requires
中 dependency_links
URL 的所有不同组合,但均无济于事。我想使用像 src+file://../utils
这样的依赖项链接 URL,它会告诉 setuptools 包的源位于文件系统上的这个相对路径上。有办法做到这一点吗?
我设法在 setup.py 中提供相对本地依赖:
setup(
install_requires=[
'utils @ file://localhost/%s/../utils/' % os.getcwd().replace('\\', '/'),
],
)
但也许有人知道更好的解决方案
我遇到了同样的问题,我需要依赖同级文件夹中的模块。我偶然发现了解决方案https://caremad.io/2013/07/setup-vs-requirement/
我最终使用了requirements.txt来专门引用我想要的文件,然后使用
安装所有内容pip install -r requirements.txt
需求.txt
-e ../utils
-e .
setup.py 具有我所有其他依赖项,包括 utils。当 pip 尝试安装 app1 本身时,它意识到 utils 依赖项已被填充,因此会忽略它,同时安装其他需求。
当我想要处理一组相互关联的项目时,我使用
/setup.py develop
安装所有这些项目。
如果我错误地或后来我想让 pip 安装的模块可编辑,我会克隆源代码,并对其执行
python setup.py develop
操作,替换现有的模块。
为了确定,我删除了 virtualenv 的站点包和包本身中的引用。
当前答案没有解释如何使用
setuptools
安装 editable
,本地依赖项。
下面将安装本地依赖项作为可编辑的以便与 setuptools 一起使用。
from pip import main as pip_main
from pip._internal.network.session import PipSession
from pip._internal.models.link import Link
from pip._internal.req import parse_requirements
from pip._internal.req.req_file import ParsedRequirement
from pip._internal.req.constructors import parse_req_from_line
import os
from setuptools import find_packages, setup
def pip_to_setup(requirement: ParsedRequirement, editable=True) -> str:
'''
Convert a pip requirement to a setup.py install_requires
If `editable` then pre-install via `pip install -e ...` and return ''
Else return local path requirement
'''
requirement_parts = parse_req_from_line(
requirement.requirement,
requirement.line_source,
)
if (
isinstance(requirement_parts.link, Link)
and requirement_parts.link.is_existing_dir()
):
package_path = requirement_parts.link.file_path
if editable:
pip_main(['install', '-e', package_path])
return '' # https://medium.com/@ashley.e.shultz/python-mono-repo-with-only-built-in-tooling-7c2d52c2fc66
else:
package_name = os.path.basename(package_path)
return f'{package_name} @ file://{package_path}'
else:
return requirement.requirement
def main():
dir_path = os.path.dirname(__file__)
package_name = os.path.basename(dir_path)
requirements_path = os.path.join(dir_path, 'requirements.txt')
test_requirements_path = os.path.join(dir_path, 'requirements-test.txt')
requirements = parse_requirements(requirements_path, session=PipSession())
install_requires = [pip_to_setup(r) for r in requirements]
test_requires = []
if os.path.isfile(test_requirements_path):
test_requirements = parse_requirements(test_requirements_path, session=PipSession())
test_requires.extend(pip_to_setup(r) for r in test_requirements)
setup(
name=package_name,
setup_requires=['setuptools_scm'],
install_requires=install_requires,
tests_require=test_requires,
extras_require={'test': test_requires},
packages=find_packages(where='src'),
package_dir={'': 'src'},
package_data={'': ['**/*']},
)
if __name__ == '__main__':
main()
(您可能需要根据您的项目结构修改
packages
和 package_dir
。
boto3
../your_local_package