这个`setup.py`有什么问题?
我在使用 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
时,发生了一些奇怪的事情:
生成了一个
MANIFEST
文件。在现有的
my_package
文件夹内,创建了一个 副本 的my_package
文件夹(不过我觉得缺少了一些与设置相关的文件)。生成了一个
dist
文件夹,里面有一个压缩文件,压缩文件里有一个以包名命名的文件夹,但我希望的整个包并没有在里面,只有两个文件:setup.py
和PKG-INFO
。
我哪里做错了?我该如何让 sdist
正常工作呢?
2 个回答
这个问题在这里讲得很清楚:
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文件仍然会在你当前的目录中创建,但我希望这不是个问题。
不要这样做:
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目录下的包进行分发。