这个`setup.py`有什么问题?

0 投票
2 回答
1940 浏览
提问于 2025-04-15 15:20

我在使用 setup.py 时遇到了一些问题,特别是在执行 sdist 的时候。经过一番研究,我发现问题主要集中在这里。我有以下的文件夹结构:

my_package\
    my_subpackage\
        __init__.py
        deep_module.py
    __init__.py
    module.py
    setup.py

这是我在 setup.py 中的内容:

#!/usr/bin/env python

from distutils.core import setup
import distutils

setup(
    name='a',
    version='0.1',
    description='a',
    author='a',
    author_email='a@a.com',
    url='http://a.org',
    packages=['my_package','my_package.my_subpackage'],
    package_dir={'': '..'},
    license= "a",
    long_description = 'aaa',

)

(这里的 'aaa' 只是占位符。)

总的来说,当我执行 setup.py install 时,一切都还不错,但当我尝试执行 setup.py sdist 时,发生了一些奇怪的事情:

  1. 生成了一个 MANIFEST 文件。

  2. 在现有的 my_package 文件夹内,创建了一个 副本my_package 文件夹(不过我觉得缺少了一些与设置相关的文件)。

  3. 生成了一个 dist 文件夹,里面有一个压缩文件,压缩文件里有一个以包名命名的文件夹,但我希望的整个包并没有在里面,只有两个文件:setup.pyPKG-INFO

我哪里做错了?我该如何让 sdist 正常工作呢?

2 个回答

6

这个问题在这里讲得很清楚:

Setuptools有很多默默无闻的失败模式。其中一个就是在sdist发布时没有包含所有文件(其实不算真正的失败,你可以查查手册,但默认的行为让人意外)。这篇文章将作为这个问题的谷歌自助解答,直到我们得到新的、更好的Distribute来解决我们所有的问题。

正如评论所指出的,问题(设计不当)其实出在distutils上——setuptools只是没有修复它(如果你用的是svn,情况会好一些)。

我可以重现你所观察到的问题,也就是说,文件名稍微缩短了一点,我有:

$ ls -lR
total 8
-rw-r--r--  1 aleax  eng    0 Oct 24 11:25 __init__.py
-rw-r--r--  1 aleax  eng    0 Oct 24 11:25 modu.py
drwxr-xr-x  4 aleax  eng  136 Oct 24 11:25 mysub
-rw-r--r--  1 aleax  eng  323 Oct 24 11:26 setup.py

./mysub:
total 0
-rw-r--r--  1 aleax  eng  0 Oct 24 11:25 __init__.py
-rw-r--r--  1 aleax  eng  0 Oct 24 11:25 deepmod.py

然后运行python setup.py sdist会产生(还有一些警告):

$ ls -lR
total 16
-rw-r--r--  1 aleax  eng  104 Oct 24 11:35 MANIFEST
-rw-r--r--  2 aleax  eng    0 Oct 24 11:25 __init__.py
drwxr-xr-x  3 aleax  eng  102 Oct 24 11:35 dist
-rw-r--r--  2 aleax  eng    0 Oct 24 11:25 modu.py
drwxr-xr-x  5 aleax  eng  170 Oct 24 11:35 mypack
drwxr-xr-x  4 aleax  eng  136 Oct 24 11:25 mysub
-rw-r--r--  1 aleax  eng  323 Oct 24 11:26 setup.py

./dist:
total 8
-rw-r--r--  1 aleax  eng  483 Oct 24 11:35 a-0.1.tar.gz

./mypack:
total 0
-rw-r--r--  2 aleax  eng    0 Oct 24 11:25 __init__.py
-rw-r--r--  2 aleax  eng    0 Oct 24 11:25 modu.py
drwxr-xr-x  4 aleax  eng  136 Oct 24 11:35 mysub

./mypack/mysub:
total 0
-rw-r--r--  2 aleax  eng  0 Oct 24 11:25 __init__.py
-rw-r--r--  2 aleax  eng  0 Oct 24 11:25 deepmod.py

./mysub:
total 0
-rw-r--r--  2 aleax  eng  0 Oct 24 11:25 __init__.py
-rw-r--r--  2 aleax  eng  0 Oct 24 11:25 deepmod.py

一个解决方案是按照以下方式更改目录结构(从当前的mypack目录开始):

$ mkdir mypack
$ mv __init__.py modu.py mysub/ mypack
$ touch README.txt

这样就得到了:

$ ls -lR
total 8
-rw-r--r--  1 aleax  eng    0 Oct 24 11:37 README.txt
drwxr-xr-x  5 aleax  eng  170 Oct 24 11:37 mypack
-rw-r--r--  1 aleax  eng  323 Oct 24 11:26 setup.py

./mypack:
total 0
-rw-r--r--  1 aleax  eng    0 Oct 24 11:25 __init__.py
-rw-r--r--  1 aleax  eng    0 Oct 24 11:25 modu.py
drwxr-xr-x  4 aleax  eng  136 Oct 24 11:25 mysub

./mypack/mysub:
total 0
-rw-r--r--  1 aleax  eng  0 Oct 24 11:25 __init__.py
-rw-r--r--  1 aleax  eng  0 Oct 24 11:25 deepmod.py

(并且消除了一个警告,就是关于README的那个——关于缺少MANIFEST.in的警告显然还在;-)。另外,把setup.py中的一行改成:

package_dir={'': '.'},

现在,运行python setup.py sdist后,你会得到一个不错的压缩包:

$ tar tvf dist/a-0.1.tar.gz 
drwxr-xr-x aleax/eng         0 2009-10-24 11:40:05 a-0.1/
drwxr-xr-x aleax/eng         0 2009-10-24 11:40:05 a-0.1/mypack/
-rw-r--r-- aleax/eng         0 2009-10-24 11:25:30 a-0.1/mypack/__init__.py
-rw-r--r-- aleax/eng         0 2009-10-24 11:25:30 a-0.1/mypack/modu.py
drwxr-xr-x aleax/eng         0 2009-10-24 11:40:05 a-0.1/mypack/mysub/
-rw-r--r-- aleax/eng         0 2009-10-24 11:25:30 a-0.1/mypack/mysub/__init__.py
-rw-r--r-- aleax/eng         0 2009-10-24 11:25:30 a-0.1/mypack/mysub/deepmod.py
-rw-r--r-- aleax/eng       156 2009-10-24 11:40:05 a-0.1/PKG-INFO
-rw-r--r-- aleax/eng         0 2009-10-24 11:37:41 a-0.1/README.txt
-rw-r--r-- aleax/eng       322 2009-10-24 11:39:46 a-0.1/setup.py

当然,MANIFEST文件仍然会在你当前的目录中创建,但我希望这不是个问题。

4

不要这样做:

my_package\
    my_subpackage\
        __init__.py
        deep_module.py
    __init__.py
    module.py
    setup.py

试试这样:

my_package_source\
    setup.py
    README.txt
    my_package\
        my_subpackage\
            __init__.py
            deep_module.py
        __init__.py
        module.py

其实你不一定需要一个README文件,这只是用来展示你项目文件夹根目录下可能放些什么东西。

=== 编辑 ======================================

我需要详细说明一下。运行之后,你的目录应该看起来像这样:

my_package_source\
    setup.py
    README.txt
    MANIFEST
    PKG-INFO
    dist\
        my_package_0.X.tar.gz (or .zip on windows I believe)
    my_package\
        my_subpackage\
            __init__.py
            deep_module.py
        __init__.py
        module.py

使用dist目录下的包进行分发。

撰写回答