pip 安装。仅创建 dist-info 而不是包

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

我正在尝试制作一个 python 包,我想在本地使用

pip install .
安装它。包名称列在
pip freeze
中,但
import <package>
会导致错误
No module named <package>
。此外,site-packages 文件夹仅包含 dist-info 文件夹。
find_packages()
能够找到包裹。我错过了什么?

import io
import os
import sys
from shutil import rmtree

from setuptools import find_packages, setup, Command

# Package meta-data.
NAME = '<package>'
DESCRIPTION = 'description'
URL = ''
EMAIL = 'email'
AUTHOR = 'name'

# What packages are required for this module to be executed?
REQUIRED = [
    # 'requests', 'maya', 'records',
]

# The rest you shouldn't have to touch too much :)
# ------------------------------------------------
# Except, perhaps the License and Trove Classifiers!
# If you do change the License, remember to change the Trove Classifier for that!

here = os.path.abspath(os.path.dirname(__file__))



# Where the magic happens:
setup(
    name=NAME,
    #version=about['__version__'],
    description=DESCRIPTION,
    # long_description=long_description,
    author=AUTHOR,
    author_email=EMAIL,
    url=URL,
    packages=find_packages(),
    # If your package is a single module, use this instead of 'packages':
    # py_modules=['mypackage'],

    # entry_points={
    #     'console_scripts': ['mycli=mymodule:cli'],
    # },
    install_requires=REQUIRED,
    include_package_data=True,
    license='MIT',
    classifiers=[
        # Trove classifiers
        # Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
        'License :: OSI Approved :: MIT License',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Programming Language :: Python :: 3.6',
        'Programming Language :: Python :: Implementation :: CPython',
        'Programming Language :: Python :: Implementation :: PyPy'
    ],

)
python pip package setuptools setup.py
6个回答
148
投票

由于这个问题已经变得非常流行,因此以下是安装后丢失文件时要执行的诊断步骤。想象一下有一个具有以下结构的示例项目:

root
├── spam
│   ├── __init__.py
│   ├── data.txt
│   ├── eggs.py
│   └── fizz
│       ├── __init__.py
│       └── buzz.py
├── bacon.py
└── setup.py

现在我运行

pip install .
,检查软件包是否已安装:

$ pip list
Package    Version
---------- -------
mypkg      0.1    
pip        19.0.1 
setuptools 40.6.3 
wheel      0.32.3 

但在属于已安装软件包的文件列表中看不到

spam
spam/eggs.py
bacon.py
spam/fizz/buzz.py

$ pip show -f mypkg
Name: mypkg
Version: 0.1
...
Files:
  mypkg-0.1.dist-info/DESCRIPTION.rst
  mypkg-0.1.dist-info/INSTALLER
  mypkg-0.1.dist-info/METADATA
  mypkg-0.1.dist-info/RECORD
  mypkg-0.1.dist-info/WHEEL
  mypkg-0.1.dist-info/metadata.json
  mypkg-0.1.dist-info/top_level.txt

那么现在该怎么办?

通过检查车轮构建日志进行诊断

除非被告知不要这样做,否则

pip
将始终尝试构建一个wheel文件并从中安装你的包。如果以详细模式重新安装,我们可以检查车轮构建过程的日志。第一步是卸载软件包:

$ pip uninstall -y mypkg
...

然后再次安装它,但现在带有一个附加参数:

$ pip install . -vvv
...

现在如果我检查日志:

$ pip install . -vvv | grep 'adding'
  adding 'mypkg-0.1.dist-info/METADATA'
  adding 'mypkg-0.1.dist-info/WHEEL'
  adding 'mypkg-0.1.dist-info/top_level.txt'
  adding 'mypkg-0.1.dist-info/RECORD'

我注意到任何地方都没有提到

spam
目录或
bacon.py
中的文件。这意味着它们根本不包含在wheel文件中,因此不被
pip
安装。最常见的错误源是:

缺少包裹:检查
packages
参数

验证您已将

packages
参数传递给设置函数。检查您是否已提及应安装的all 软件包。如果只提及父包,则不会自动收集子包!例如,在设置脚本中

from setuptools import setup

setup(
    name='mypkg',
    version='0.1',
    packages=['spam']
)
将安装

spam
,但不会安装
spam.fizz
,因为它本身就是一个包,必须明确提及。修复它:

from setuptools import setup

setup(
    name='mypkg',
    version='0.1',
    packages=['spam', 'spam.fizz']
)

如果您有很多包,请使用

setuptools.find_packages
来自动化该过程:

from setuptools import find_packages, setup

setup(
    name='mypkg',
    version='0.1',
    packages=find_packages()  # will return a list ['spam', 'spam.fizz']
)

如果您缺少某个模块:

缺少模块:检查
py_modules
参数

在上面的例子中,安装后我会丢失

bacon.py
,因为它不属于任何包。我必须在单独的参数中提供其模块名称
py_modules
:

from setuptools import find_packages, setup

setup(
    name='mypkg',
    version='0.1',
    packages=find_packages(),
    py_modules=['bacon']
)

缺少数据文件:检查
package_data
参数

我现在已经准备好了所有源代码文件,但是

data.txt
文件仍然没有安装。位于包目录下的数据文件应通过
package_data
参数添加。修复上述设置脚本:

from setuptools import find_packages, setup

setup(
    name='mypkg',
    version='0.1',
    packages=find_packages(),
    package_data={'spam': ['data.txt']},
    py_modules=['bacon']
)

不要试图使用

data_files
参数。将数据文件放在包下并配置
package_data

修复安装脚本后,验证安装后包文件是否就位

如果我现在重新安装该软件包,我会注意到所有文件都已添加到轮子中:

$ pip install . -vvv | grep 'adding'
  adding 'bacon.py'
  adding 'spam/__init__.py'
  adding 'spam/data.txt'
  adding 'spam/eggs.py'
  adding 'spam/fizz/__init__.py'
  adding 'spam/fizz/buzz.py'
  adding 'mypkg-0.1.dist-info/METADATA'
  adding 'mypkg-0.1.dist-info/WHEEL'
  adding 'mypkg-0.1.dist-info/top_level.txt'
  adding 'mypkg-0.1.dist-info/RECORD'

它们也将在属于

mypkg
:

的文件列表中可见
$ pip show -f mypkg
Name: mypkg
Version: 0.1
...
Files:
  __pycache__/bacon.cpython-36.pyc
  bacon.py
  mypkg-0.1.dist-info/INSTALLER
  mypkg-0.1.dist-info/METADATA
  mypkg-0.1.dist-info/RECORD
  mypkg-0.1.dist-info/WHEEL
  mypkg-0.1.dist-info/top_level.txt
  spam/__init__.py
  spam/__pycache__/__init__.cpython-36.pyc
  spam/__pycache__/eggs.cpython-36.pyc
  spam/data.txt
  spam/eggs.py
  spam/fizz/__init__.py
  spam/fizz/__pycache__/__init__.cpython-36.pyc
  spam/fizz/__pycache__/buzz.cpython-36.pyc
  spam/fizz/buzz.py

2
投票

我遇到了同样的问题,更新

setuptools
有帮助:

python3 -m pip install --upgrade pip setuptools wheel

之后,重新安装软件包,它应该可以正常工作:)


2
投票

确保您的

src
文件位于
example_package_YOUR_USERNAME_HERE
中(这是文档中使用的示例包名称)而不是位于
src
中。错误地将文件放入
src
可能会产生问题中描述的效果。

参考:https://packaging.python.org/en/latest/tutorials/packaging-projects/

包应该这样设置:

packaging_tutorial/
└── src/
    └── example_package_YOUR_USERNAME_HERE/
        ├── __init__.py
        └── example.py

1
投票

对我来说,如果你这样做,我会注意到一些奇怪的事情:

# Not in the setup.py directory
python /path/to/folder/setup.py bdist_wheel

当您安装wheel时,它只会在您的site-packages文件夹中安装.dist-info文件夹。

但是,如果您这样做:

cd /path/to/folder \
&& python setup.py bdist_wheel

轮子将包含您的所有文件。


0
投票

如果您使用的是 Windows 10+,确保安装正确的一种方法是单击左下角的“开始”并搜索 cmd.exe,然后右键单击“命令提示符”(确保您选择“以管理员身份运行”)。输入“cd

path to your Python 3.X installation
”。您可以在文件资源管理器中找到此路径(转到安装 Python 的文件夹),然后在顶部找到该路径。复制这个,然后把它放在我上面写的地方
path to your Python 3.X installation
。完成此操作并单击 Enter 后,输入“python -m pip install
package
”(
package
表示您要安装的软件包)。您的 Python 程序现在应该可以完美运行。


0
投票

更新2024:现在推荐使用

pyproject.toml
代替
setup.py
。它是由PEP 517PEP 518引入的。 您可以在这里找到两种方法之间的区别

您需要做的就是确保模块的根目录和所有子目录中有空的

__init__.py
。您还需要创建如下所示的
pyproject.toml
文件,

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[metadata]
name = "project"
version = "0.0.1"

[tool.setuptools.packages]
find = {}  # Scan the project directory with the default parameters

[project]
name = "project"
version = "0.0.1"
authors = [
  { name="your_name", email="your_email" },
]
description = "Sample project "
readme = "README.md"
requires-python = ">=3.8"

很棒的文章解释了设置这里

© www.soinside.com 2019 - 2024. All rights reserved.