Ich versuche ein Python-Paket zu erstellen, das ich mit pip install .
lokal installieren möchte. Der Paketname ist in pip freeze
aufgeführt, aber import <package>
führt zu einem Fehler No module named <package>
. Auch der Site-Packages-Ordner enthält nur einen Dist-Info-Ordner. find_packages()
kann Pakete finden. Was vermisse ich?
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'
],
)
Da die Frage sehr populär geworden ist, folgen Sie den Diagnoseschritten, die durchgeführt werden müssen, wenn nach der Installation Dateien fehlen. Stellen Sie sich ein Beispielprojekt mit folgender Struktur vor:
root
├── spam
│ ├── __init__.py
│ ├── data.txt
│ ├── eggs.py
│ └── fizz
│ ├── __init__.py
│ └── buzz.py
├── bacon.py
└── setup.py
Jetzt führe ich pip install .
aus und überprüfe, ob das Paket installiert ist:
$ pip list
Package Version
---------- -------
mypkg 0.1
pip 19.0.1
setuptools 40.6.3
wheel 0.32.3
sehen Sie jedoch weder spam
noch spam/eggs.py
noch bacon.py
oder spam/fizz/buzz.py
in der Liste der Dateien, die zum installierten Paket gehören:
$ 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
Was soll ich jetzt tun?
Wenn dies nicht gesagt wird, versucht pip
immer, eine Raddatei zu erstellen und Ihr Paket daraus zu installieren. Bei einer Neuinstallation im ausführlichen Modus können wir das Protokoll für den Radaufbau prüfen. Zunächst müssen Sie das Paket deinstallieren:
$ pip uninstall -y mypkg
...
dann installieren Sie es erneut, aber jetzt mit einem zusätzlichen Argument:
$ pip install . -vvv
...
Wenn ich jetzt das Protokoll inspiziere:
$ 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'
Ich stelle fest, dass an keiner Stelle Dateien aus dem Verzeichnis spam
oder bacon.py
erwähnt werden. Dies bedeutet, dass sie einfach nicht in der Raddatei enthalten waren und daher nicht von pip
installiert wurden. Die häufigsten Fehlerquellen sind:
packages
Stellen Sie sicher, dass Sie das Argument packages
an die Setup-Funktion übergeben haben. Überprüfen Sie, ob Sie all der Pakete, die installiert werden sollen, angegeben haben. Unterpakete werden nicht automatisch abgeholt, wenn nur das übergeordnete Paket erwähnt wird! Zum Beispiel im Setup-Skript
from setuptools import setup
setup(
name='mypkg',
version='0.1',
packages=['spam']
)
spam
wird installiert, jedoch nicht spam.fizz
, da es selbst ein Paket ist und explizit erwähnt werden muss. Es reparieren:
from setuptools import setup
setup(
name='mypkg',
version='0.1',
packages=['spam', 'spam.fizz']
)
Wenn Sie viele Pakete haben, automatisieren Sie den Vorgang mit 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']
)
Falls Sie ein Modul vermissen:
py_modules
In den obigen Beispielen fehlt nach der Installation bacon.py
, da er zu keinem Paket gehört. Ich muss seinen Modulnamen im separaten Argument py_modules
angeben:
from setuptools import find_packages, setup
setup(
name='mypkg',
version='0.1',
packages=find_packages(),
py_modules=['bacon']
)
package_data
Ich habe jetzt alle Quellcodedateien installiert, aber die data.txt
-Datei ist immer noch nicht installiert. Datendateien unter Paketverzeichnissen sollten über das Argument package_data
hinzugefügt werden. Das obige Setup-Skript korrigieren:
from setuptools import find_packages, setup
setup(
name='mypkg',
version='0.1',
packages=find_packages(),
package_data={'spam': ['data.txt']},
py_modules=['bacon']
)
Seien Sie nicht versucht, das Argument data_files
zu verwenden. Legen Sie die Datendateien unter ein Paket und konfigurieren Sie stattdessen package_data
.
Wenn ich das Paket jetzt erneut installiere, werden alle Dateien zum Rad hinzugefügt:
$ 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'
Sie werden auch in der Liste der Dateien angezeigt, die zu mypkg
gehören:
$ 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
Wenn Sie Windows 10+ verwenden, können Sie sicherstellen, dass alle korrekten Installationen vorhanden sind. Klicken Sie dazu links unten auf Start, suchen Sie nach cmd.exe und klicken Sie mit der rechten Maustaste auf "Eingabeaufforderung" wählen Sie "Als Administrator ausführen"). Geben Sie "cd path to your Python 3.X installation
" ein. Sie finden diesen Pfad im Datei-Explorer (gehen Sie zu dem Ordner, in dem Python installiert ist) und dann oben. Kopiere das und füge es dort ein, wo ich oben path to your Python 3.X installation
geschrieben habe. Wenn Sie dies getan haben und auf die Eingabetaste klicken, geben Sie "python -m pip install package
" ein (package
steht für das Paket, das Sie installieren möchten). Ihr Python-Programm sollte jetzt einwandfrei funktionieren.