我无法弄清楚如何使用setuptools安装我的软件包,我已经尝试阅读它上面的文档和SO帖子,但我无法让它正常工作。我正在尝试使用一个简单的helloworld应用程序。这是我得到了多远:
helloworld.py:
print("Hello, World!")
的README.txt:
Hello, World! readme
MANIFEST.in:
recursive-include images *.gif
setup.py:
from setuptools import setup, find_packages
setup(
name='helloworld',
version='0.1',
license='BSD',
author='gyeh',
author_email='hello@world.com',
url='http://www.hello.com',
long_description="README.txt",
packages=find_packages(),
scripts = ['helloworld.py'],
package_data={
"" : ["images/*.gif"]
},
data_files=[('images', ['images/hello.gif'])],
description="Hello World testing setuptools",
)
我有一个名为images / hello.gif的空白文件,我希望将其作为附加数据包含在我的包中。文件夹结构如下所示:
testsetup/
|-- helloworld.py
|-- images/
|-- --- hello.gif
|-- MANIFEST.in
|-- README.txt
|-- setup.py
当我运行python setup.py sdist
时,它会成功生成dist
和helloworld.egg-info
。当我在egg-info下查看SOURCES.txt时,它包含脚本和images文件夹下的图像,而dist下的tarball也包含它们。
然而,当我尝试在tarball上运行pip install --user helloworld-0.1.tar.gz
时,它成功安装了它,但我找不到程序文件helloworld.py和images / hello.gif。
当我查看$HOME/.local/lib/python3.3/site-packages/
时,我看到egg-info文件夹及其所有内容都安装在那里。但$HOME/.local/bin
文件夹甚至不存在。程序文件存储在别处吗?我在这做错了什么?我正在运行Arch Linux。
答案 0 :(得分:18)
好的,经过一番努力,我终于设法让一个简单的" hello world" 示例为setuptools工作。 Python文档通常很棒,但我希望文档在这方面更好。
我将写一篇关于我如何实现这一目标的相当详细的指南,并且我将假设读者没有关于此主题的先前背景。我希望这对其他人有用......
为了设置这个示例,我们将创建一个包(实际上是两个包,一个用于数据文件)。这是我们最终得到的目录结构:
test-setuptools/
|-- helloworld/
|-- --- hello.py
|-- --- images/
|-- --- --- hello.gif
|-- --- --- __init__.py
|-- --- __init__.py
|-- MANIFEST.in
|-- README.txt
|-- setup.py
以下是步骤:
创建helloworld
包。
1.1创建helloworld/
文件夹,如上面的目录结构所示。
1.2在__init__.py
文件夹中添加名为helloworld/
的空白文件
如果您不添加它,则无法识别包(运行touch __init__.py
以在linux / mac计算机上创建文件)。如果您希望每次导入包时都执行一些代码,请将其包含在__init__.py
文件中。
1.3创建hello.py
脚本文件以演示包功能。
以下是hello.py
的代码:
import os
"""
Open additional data files using the absolute path,
otherwise it doesn't always find the file.
"""
# The absolute path of the directoy for this file:
_ROOT = os.path.abspath(os.path.dirname(__file__))
class Hello(object):
def say_hello(self):
return "Hello, World!"
def open_image(self):
print("Reading image.gif contents:")
# Get the absolute path of the image's relative path:
absolute_image_path = os.path.join(_ROOT, 'images/hello.gif')
with open(absolute_image_path, "r") as f:
for line in f:
print(line)
1.4在images/
文件夹中创建helloworld/
文件夹
制作另一个空白__init__.py
文件,因为此文件夹也是一个包。
1.5在hello.gif
文件夹中创建images/
文件
这个文件不是一个真正的gif文件。相反,添加纯文本只是为了演示可以添加和读取非脚本文件。
我在hello.gif
中添加了以下代码:
This should be the data inside hello.gif...
...but this is just to demonstrate setuptools,
so it's a dummy gif containing plain text
1.6测试你的包裹
从python
文件夹运行test-setuptools
,这将打开python解释器
输入import helloworld.hello
以导入hello.py
包中的helloworld
脚本。导入应该成功,表明您已成功创建包。通过键入images/
确保import helloworld.images
文件夹中的包也可以正常工作
尝试实例化我们在hello.py
中编写的对象。键入以下命令以确保一切按预期工作:
hey = helloworld.hello.Hello()
hey.say_hello()
hey.open_image()
创建setup.py
文件和其余文件
2.1创建一个简单的README.txt
文件。我的内容只有Hello, World! Readme
。
2.2创建一个MANIFEST.in
文件,其中包含以下内容:
include helloworld/images/hello.gif
。
这非常重要,因为它告诉setuptools在源代码分发中包含其他数据(我们将在后面的步骤中生成)。如果没有这个,您将无法在软件包中安装其他非.py
数据。有关其他详细信息和命令,请参阅this。
2.3创建setup.py
文件(参见下面的代码)
最重要的属性是packages
,include_package_data
和package_data
。
packages
属性包含要包含在setuptools中的软件包列表。我们希望同时包含helloworld
包和helloworld.images
包,其中包含我们的其他数据hello.gif
。
您可以通过添加from setuptools import find_packages
导入并运行导入的find_packages()
函数,使setuptools自动找到这些内容。从test-setuptools
文件夹运行解释器并测试此命令以查看找到的软件包
。
package_data
属性告诉setuptools包含其他数据。这个命令,helloworld.images
包和MANIFEST.in
文件允许您安装其他数据。
'helloworld.images' : ['hello.gif']
键/值对告诉setuptools在hello.gif
包中包含helloworld.images
(如果存在)。您还可以说'' : ['*.gif']
将任何.gif文件包含在任何包含的包中
include_package_data
属性设置为True
也是必要的
您可以像我一样包含其他元数据(我认为author
是必要的)。添加分类器是个好主意。其他信息可以在here找到。
以下是整个setup.py
代码:
from setuptools import setup
setup(
name='helloworld',
version='0.1',
license='BSD',
author='gyeh',
author_email='hello@world.com',
url='http://www.hello.com',
long_description="README.txt",
packages=['helloworld', 'helloworld.images'],
include_package_data=True,
package_data={'helloworld.images' : ['hello.gif']},
description="Hello World testing setuptools",
)
。
3.使用setuptools安装并测试您的包。
3.1 Create the source distribution
从python setup.py sdist
文件夹运行test-setuptools/
以生成源代码分发
这将创建一个包含您的包的dist/
文件夹,以及一个包含helloworld.egg-info/
等元数据的SOURCE.txt
文件夹。
检查SOURCE.txt
,看看您的hello.gif
图片文件是否包含在内
打开.tar.gz
文件夹下的dist/
文件。您应该看到我们之前制作的目录结构中描述的所有文件,包括hello.gif
和hello.py
。
3.2 Install the distribution
通过从pip install --user helloworld-0.1.tar.gz
文件夹运行dist/
来安装.tar.gz分发文件
通过运行pip list
检查包是否已成功安装。包helloworld
应该在那里。
那就是它!现在你应该能够在任何文件夹下测试你的包。在test-setuptools
以外的任何文件夹中打开解释器,然后尝试使用import helloworld.hello
导入包。它应该工作。然后尝试使用命令实例化对象,并再次使用hey.open_image()
命令打开图像文件。它应该仍然有用!
您可以通过卸载软件包来准确查看pip安装的文件及其位置。 我看起来像这样:
[gyeh@gyeh package]$ pip uninstall helloworld
Uninstalling helloworld:
/home/gyeh/.local/lib/python3.3/site-packages/helloworld-0.1-py3.3.egg-info
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/__init__.py
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/__pycache__/__init__.cpython-33.pyc
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/__pycache__/hello.cpython-33.pyc
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/hello.py
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/images/__init__.py
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/images/__pycache__/__init__.cpython-33.pyc
/home/gyeh/.local/lib/python3.3/site-packages/helloworld/images/hello.gif
Proceed (y/n)? y
Successfully uninstalled helloworld
如您所见,它成功安装了附加数据文件hello.gif
,并且因为我们将相对路径转换为hello.py
中的绝对路径,所以它可以正常读取文件。
然后,您可以在PyPI上共享此包,供世界其他地方使用!上传到PyPI的说明非常简单,可以找到here和here。
一旦在PyPI中联机,人们就可以使用pip search
搜索您的包裹。或者,运行pip install --user [package-name]
将告诉pip在线PyPI目录中搜索该包名。如果它存在,它将安装它。
您可以为PyPI中的任何python包运行该命令,以便于安装,这样您就不会使用构建文件。
我希望这可以为人们带来一些麻烦。