使用 setup.py 自定义 python 包目录布局
Customizing python package directory layout with setup.py
假设我有以下目录结构:
src/
└── python/
└── generated/
├── __init__.py
├── a.py
└── lib/
├── __init__.py
└── b.py
我的 setup.py
需要什么样子才能创建目录布局如下的 dist:
src/
└── python/
├── __init__.py
├── a.py
└── lib/
├── __init__.py
└── b.py
目标是简单地删除 generated
文件夹。我已经尝试了 package_dir
的无穷无尽的变体,但除了原始目录结构之外什么也得不到。
首先,这是我的解决方案:
#!/usr/bin/env python
import os, shutil
from setuptools import setup
from setuptools.command.build_py import build_py
class BuildPyCommand(build_py):
"""Custom build command."""
def run(self):
shutil.rmtree('src.tmp', ignore_errors=True)
os.mkdir('src.tmp')
shutil.copytree('src/python/generated', 'src.tmp/python')
build_py.run(self)
setup(cmdclass={ 'build_py': BuildPyCommand },
name='Blabla',
version='1.0',
description='best desc ever',
author='Me',
packages=['python', 'python.lib'],
package_dir={'': 'src.tmp'},
setup_requires=['wheel']
)
您可以使用以下方式生成您的发行版:
python setup.py build bdist_wheel
想法是执行两个步骤构建:
- 我生成了有效的源结构
- 我建了这个临时建筑
我用轮子交付它,因为它不需要未来的用户理解我的技巧。如果你尝试使用源分发,你会注意到你需要将生成的文件作为数据发布(不难,但很麻烦,而且,我想你会想对你的用户隐藏你的技巧)。
但是,我认为您的流程存在设计缺陷。文件src/python/generated/__init__.py
,假设是一个模块<something>.generated
,最终变成了你的<something>.python
,这很麻烦。生成有效的 Python 结构会更简单、更健壮:src/generated/python/__init__.py
。 setup.py 会变得微不足道,你的生成器也不会更复杂。
您的 setup.py
应该放在您的 src
目录中,并且应该如下所示:
#!/usr/bin/env python3
import setuptools
setuptools.setup(
name='Thing',
version='1.2.3',
packages=[
'python',
'python.lib',
],
package_dir={
'python': 'python/generated',
},
)
注意 package_dir
设置。它指示 setuptools
从目录 python/generated
中获取 python
包的代码。在 built 发行版中,您将找到正确的目录结构。
假设我有以下目录结构:
src/
└── python/
└── generated/
├── __init__.py
├── a.py
└── lib/
├── __init__.py
└── b.py
我的 setup.py
需要什么样子才能创建目录布局如下的 dist:
src/
└── python/
├── __init__.py
├── a.py
└── lib/
├── __init__.py
└── b.py
目标是简单地删除 generated
文件夹。我已经尝试了 package_dir
的无穷无尽的变体,但除了原始目录结构之外什么也得不到。
首先,这是我的解决方案:
#!/usr/bin/env python
import os, shutil
from setuptools import setup
from setuptools.command.build_py import build_py
class BuildPyCommand(build_py):
"""Custom build command."""
def run(self):
shutil.rmtree('src.tmp', ignore_errors=True)
os.mkdir('src.tmp')
shutil.copytree('src/python/generated', 'src.tmp/python')
build_py.run(self)
setup(cmdclass={ 'build_py': BuildPyCommand },
name='Blabla',
version='1.0',
description='best desc ever',
author='Me',
packages=['python', 'python.lib'],
package_dir={'': 'src.tmp'},
setup_requires=['wheel']
)
您可以使用以下方式生成您的发行版:
python setup.py build bdist_wheel
想法是执行两个步骤构建:
- 我生成了有效的源结构
- 我建了这个临时建筑
我用轮子交付它,因为它不需要未来的用户理解我的技巧。如果你尝试使用源分发,你会注意到你需要将生成的文件作为数据发布(不难,但很麻烦,而且,我想你会想对你的用户隐藏你的技巧)。
但是,我认为您的流程存在设计缺陷。文件src/python/generated/__init__.py
,假设是一个模块<something>.generated
,最终变成了你的<something>.python
,这很麻烦。生成有效的 Python 结构会更简单、更健壮:src/generated/python/__init__.py
。 setup.py 会变得微不足道,你的生成器也不会更复杂。
您的 setup.py
应该放在您的 src
目录中,并且应该如下所示:
#!/usr/bin/env python3
import setuptools
setuptools.setup(
name='Thing',
version='1.2.3',
packages=[
'python',
'python.lib',
],
package_dir={
'python': 'python/generated',
},
)
注意 package_dir
设置。它指示 setuptools
从目录 python/generated
中获取 python
包的代码。在 built 发行版中,您将找到正确的目录结构。