如何让 setuptools(或分发)从本地文件系统安装软件包

问题描述 投票:0回答:4

是否可以在

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 包的源位于文件系统上的这个相对路径上。有办法做到这一点吗?

python packaging setuptools distribute
4个回答
10
投票

我设法在 setup.py 中提供相对本地依赖:

setup(
    install_requires=[
        'utils @ file://localhost/%s/../utils/' % os.getcwd().replace('\\', '/'),
        ],
    )

但也许有人知道更好的解决方案


7
投票

我遇到了同样的问题,我需要依赖同级文件夹中的模块。我偶然发现了解决方案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 依赖项已被填充,因此会忽略它,同时安装其他需求。


0
投票

当我想要处理一组相互关联的项目时,我使用

/setup.py develop
安装所有这些项目。

如果我错误地或后来我想让 pip 安装的模块可编辑,我会克隆源代码,并对其执行

python setup.py develop
操作,替换现有的模块。

为了确定,我删除了 virtualenv 的站点包和包本身中的引用。


0
投票

当前答案没有解释如何使用

setuptools
安装
editable
,本地依赖项。

下面将安装本地依赖项作为可编辑的以便与 setuptools 一起使用。

设置.py

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

需求示例.txt

boto3
../your_local_package
© www.soinside.com 2019 - 2024. All rights reserved.