假设你有一个名为proj
的项目,在这个项目中你有以下结构:
proj/
dists/
doc/
src/
__init__.py
xyz.py
abc.py
test/
setup.py
正如您所看到的,项目的所有内容都在src
子文件夹中。如何从src
文件夹中创建distutils发行包?
我的天真想法,跟随the tutorial,就像这样写setup.py
:
#omitting basics
setup(
name='proj',
packages=['src'],
package_dir={'proj':'src'}
)
但是在将生成的软件包安装到我的系统后,我仍然需要导入src.xyz
而不是proj.xyz
,这将是目标和预期结果。
答案 0 :(得分:7)
您可以通过将Python包文件放入proj/
目录来修复它:
proj/
src/
proj/
__init__.py
xyz.py
abc.py
setup.py
将setup.py
更改为:
# ...
setup(
name='proj',
packages=['proj'],
package_dir={'':'src'}
)
distutils不需要它,但是其他工具可能希望__init__.py
文件的父目录名与Python包名相同,即在这种情况下为proj
。
答案 1 :(得分:3)
这是由于此处报告的setuptools中的错误:https://github.com/pypa/setuptools/issues/250
基本上,它确实有效但不是开发模式。现在你有3个解决方案:
src
包符号链接为proj
(并在投标时忽略它),它将开箱即用,但很脏src
更改为proj
proj
中创建一个子目录src
,并使用以下选项:packages=['proj'], package_dir={'proj': 'src/proj'},
答案 2 :(得分:0)
以Jfs' Answer为基础,如果像我一样,您已经建立了一个目录结构,并且由于其他原因您不希望/不能更改它,那么一种解决方案是临时复制要打包的所有代码然后构建它。
这是一个带有目标的makefile,该文件将src中的所有文件复制到临时位置,然后调用setup.py来构建程序包,然后最终对其进行清理。
SRC_DIR='src'
TEMP_PACKAGE_DIR='your_shiny_package'
package: prepare_package_dir build_package deploy_package remove_package_dir
# I'm using gemfury, your deployment will probably look different
deploy_package:
twine upload --repository fury dist/* --verbose
clean_package:
rm -r dist || echo 'dist removed'
rm -r ${TEMP_PACKAGE_DIR}.egg-info || echo 'egg-info removed'
build_package: clean_package
python setup.py sdist
prepare_package_dir:
mkdir ${TEMP_PACKAGE_DIR}
cp -R ${SRC_DIR}/* ${TEMP_PACKAGE_DIR}/
mv ${TEMP_PACKAGE_DIR} ${SRC_DIR}/${TEMP_PACKAGE_DIR}
remove_package_dir:
rm -rf ${SRC_DIR}/${TEMP_PACKAGE_DIR}
然后是一个setup.py,看起来像这样:
setup(
name='your_shiny_package',
version=version,
description='some great package...',
long_description=readme,
url='https://whereever',
author='you',
packages=['src/your_shiny_package'],
install_requires=parse_all_requirements(),
zip_safe=False,
include_package_data=True)
可能不是最有效的,但是省去了您永久性地重新构建整个仓库的麻烦。
用法:作为构建管道的一部分或手动调用make package
。
答案 3 :(得分:0)
您可以先使用 find_packages
查找 src
中的所有包名称,然后手动将它们重命名为所需名称。最后,使用 package_dir
选项指定包约定。
import re
from setuptools import find_packages, setup
PACKAGE_NAME = 'proj'
SOURCE_DIRECTORY = 'src'
SOURCE_PACKAGE_REGEX = re.compile(rf'^{SOURCE_DIRECTORY}')
source_packages = find_packages(include=[SOURCE_DIRECTORY, f'{SOURCE_DIRECTORY}.*'])
proj_packages = [SOURCE_PACKAGE_REGEX.sub(PACKAGE_NAME, name) for name in source_packages]
setup(
name=PACKAGE_NAME,
packages=proj_packages,
package_dir={PACKAGE_NAME: SOURCE_DIRECTORY},
...
)
答案 4 :(得分:-4)
您可以尝试在调用src
功能之前将PYTHONPATH
文件夹添加到setup
:
import sys, os
src_path = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'src')
sys.path.append(src_path)
而且,为了安全起见,您可以更改工作目录:
os.chdir(src_path)
之后,一切都会好的。
从内部打包应用程序支持的其他一些工具。我认为这是setuptools,结果是它的PyInstaller。但基本上,这就是应该做的,只需要直接导入你的包。
结果是distutils有package_dir
指令。这就是您应该使用的内容,但只有将您的包添加到PYTHONPATH
可能才能正常工作。