一个简单的Hello World setuptools包并用pip安装它

时间:2014-02-26 19:31:03

标签: python pip setuptools distutils pypi

我无法弄清楚如何使用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时,它会成功生成disthelloworld.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。

1 个答案:

答案 0 :(得分:18)

好的,经过一番努力,我终于设法让一个简单的" hello world" 示例为setuptools工作。 Python文档通常很棒,但我希望文档在这方面更好。

我将写一篇关于我如何实现这一目标的相当详细的指南,并且我将假设读者没有关于此主题的先前背景。我希望这对其他人有用......

为了设置这个示例,我们将创建一个包(实际上是两个包,一个用于数据文件)。这是我们最终得到的目录结构:

test-setuptools/
|-- helloworld/
|-- --- hello.py
|-- --- images/
|-- --- --- hello.gif
|-- --- --- __init__.py
|-- --- __init__.py
|-- MANIFEST.in
|-- README.txt
|-- setup.py

以下是步骤:

  1. 创建helloworld包。
    1.1创建helloworld/文件夹,如上面的目录结构所示。

    1.2在__init__.py文件夹中添加名为helloworld/的空白文件 如果您不添加它,则无法识别包(运行touch __init__.py以在linux / mac计算机上创建文件)。如果您希望每次导入包时都执行一些代码,请将其包含在__init__.py文件中。

    1.3创建hello.py脚本文件以演示包功能。

  2. 以下是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. 1.4在images/文件夹中创建helloworld/文件夹 制作另一个空白__init__.py文件,因为此文件夹也是一个包。

      1.5在hello.gif文件夹中创建images/文件 这个文件不是一个真正的gif文件。相反,添加纯文本只是为了演示可以添加和读取非脚本文件。

    2. 我在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. 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()

      2. 创建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文件(参见下面的代码) 最重要的属性是packagesinclude_package_datapackage_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找到。

      3. 以下是整个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.gifhello.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的说明非常简单,可以找到herehere

        一旦在PyPI中联机,人们就可以使用pip search搜索您的包裹。或者,运行pip install --user [package-name]将告诉pip在线PyPI目录中搜索该包名。如果它存在,它将安装它。

        您可以为PyPI中的任何python包运行该命令,以便于安装,这样您就不会使用构建文件。

        我希望这可以为人们带来一些麻烦。