ฉันพบโพสต์นี้ในขณะที่ติดปัญหาเดียวกัน
ประสบการณ์ของฉันขัดแย้งกับประสบการณ์ในคำตอบอื่น ๆ
include_package_data=True
รวมข้อมูลใน bdist! คำอธิบายในsetuptools
เอกสารประกอบ
ขาดบริบทและเคล็ดลับในการแก้ปัญหา แต่
include_package_data
ทำงานได้ตามที่โฆษณา
การตั้งค่าของฉัน:
- Windows / Cygwin
- git เวอร์ชัน 2.21.0
- การแจกจ่าย Python 3.8.1 ของ Windows
setuptools
v47.3.1
check-manifest
v0.42
นี่คือคำแนะนำวิธีการของฉัน
วิธีรวมข้อมูลแพ็คเกจ
นี่คือโครงสร้างไฟล์สำหรับโครงการที่ฉันเผยแพร่บน PyPI (ติดตั้งแอปพลิเคชันใน__main__.py
)
├── LICENSE.md
├── MANIFEST.in
├── my_package
│ ├── __init__.py
│ ├── __main__.py
│ └── _my_data <---- folder with data
│ ├── consola.ttf <---- data file
│ └── icon.png <---- data file
├── README.md
└── setup.py
จุดเริ่ม
นี่คือจุดเริ่มต้นทั่วไปสำหรับsetuptools.setup()
ใน
setup.py
.
setuptools.setup(
...
packages=setuptools.find_packages(),
...
)
setuptools.find_packages()
รวมแพ็คเกจทั้งหมดของฉันในการแจกจ่าย แพ็คเกจเดียวของฉันคือmy_package
.
โฟลเดอร์ย่อยที่มีข้อมูลของฉัน_my_data
ไม่ถือว่าเป็นแพคเกจโดย Python เนื่องจากไม่มีโฟลเดอร์__init__.py
จึงfind_packages()
ไม่พบ
วิธีแก้ปัญหาที่มักอ้างถึง แต่ไม่ถูกต้องคือการใส่__init__.py
ไฟล์เปล่าลง
ใน_my_data
โฟลเดอร์
นี้จะทำให้มันเป็นแพคเกจดังนั้นจึงไม่รวมถึงโฟลเดอร์
_my_data
ในการจัดจำหน่าย แต่ไฟล์ข้อมูลที่อยู่ภายใน
_my_data
จะไม่รวม
ดังนั้นการ_my_data
ทำเป็นแพ็คเกจไม่ได้ช่วยอะไร
วิธีแก้ปัญหาคือ:
sdist
มีอยู่แล้วไฟล์ข้อมูล
- เพิ่ม
include_package_data=True
เพื่อรวมไฟล์ข้อมูลไว้ในไฟล์bdist
ด้วย
การทดลอง (วิธีทดสอบวิธีแก้ปัญหา)
มีสามขั้นตอนในการทำการทดสอบที่ทำซ้ำได้:
$ rm -fr build/ dist/ my_package.egg-info/
$ check-manifest
$ python setup.py sdist bdist_wheel
ฉันจะแยกสิ่งเหล่านี้ลงทีละขั้นตอน:
- ทำความสะอาดโครงสร้างเก่า:
$ rm -fr build/ dist/ my_package.egg-info/
- เรียกใช้
check-manifest
เพื่อให้แน่ใจว่าMANIFEST.in
ตรงกับดัชนี Git ของไฟล์ภายใต้การควบคุมเวอร์ชัน:
$ check-manifest
หากMANIFEST.in
ยังไม่มีให้สร้างจากดัชนี Git ของไฟล์ภายใต้การควบคุมเวอร์ชัน:
$ check-manifest --create
นี่คือสิ่งMANIFEST.in
ที่สร้างขึ้น:
include *.md
recursive-include my_package *.png
recursive-include my_package *.ttf
ไม่มีเหตุผลที่จะแก้ไขไฟล์นี้ด้วยตนเอง
ตราบใดที่ทุกสิ่งที่ควรอยู่ภายใต้การควบคุมเวอร์ชันอยู่ภายใต้การควบคุมเวอร์ชัน (กล่าวคือเป็นส่วนหนึ่งของดัชนี Git)
check-manifest --create
ทำในสิ่งที่ถูกต้อง
หมายเหตุ: ไฟล์ไม่ได้เป็นส่วนหนึ่งของดัชนี Git หากเป็น:
- ละเว้นในไฟล์
.gitignore
- ไม่รวมอยู่ใน
.git/info/exclude
- หรือไฟล์ใหม่ที่ยังไม่ได้เพิ่มลงในดัชนี
และหากไฟล์ใด ๆ อยู่ภายใต้การควบคุมเวอร์ชันที่ไม่ควรอยู่ภายใต้การควบคุมเวอร์ชันให้check-manifest
ออกคำเตือนและระบุไฟล์ที่แนะนำให้ลบออกจากดัชนี Git
- สร้าง:
$ python setup.py sdist bdist_wheel
ตอนนี้ตรวจสอบsdist
(การแจกจ่ายต้นทาง) และbdist_wheel
(สร้างการแจกจ่าย) เพื่อดูว่ามีไฟล์ข้อมูลหรือไม่
ดูเนื้อหาของsdist
(แสดงเฉพาะบรรทัดที่เกี่ยวข้องด้านล่าง):
$ tar --list -f dist/my_package-0.0.1a6.tar.gz
my_package-0.0.1a6/
...
my_package-0.0.1a6/my_package/__init__.py
my_package-0.0.1a6/my_package/__main__.py
my_package-0.0.1a6/my_package/_my_data/
my_package-0.0.1a6/my_package/_my_data/consola.ttf <-- yay!
my_package-0.0.1a6/my_package/_my_data/icon.png <-- yay!
...
ดังนั้นsdist
ไฟล์ข้อมูลจึงรวมอยู่แล้วเนื่องจากมีรายชื่ออยู่ในMANIFEST.in
. ไม่มีอะไรเพิ่มเติมที่ต้องทำเพื่อรวมไฟล์ข้อมูลในไฟล์sdist
.
ดูเนื้อหาของbdist
(เป็นไฟล์. zip แยกวิเคราะห์ด้วยzipfile.ZipFile
):
$ python check-whl.py
my_package/__init__.py
my_package/__main__.py
my_package-0.0.1a6.dist-info/LICENSE.md
my_package-0.0.1a6.dist-info/METADATA
my_package-0.0.1a6.dist-info/WHEEL
my_package-0.0.1a6.dist-info/entry_points.txt
my_package-0.0.1a6.dist-info/top_level.txt
my_package-0.0.1a6.dist-info/RECORD
หมายเหตุ: คุณต้องสร้างcheck-whl.py
สคริปต์ของคุณเองเพื่อสร้างผลลัพธ์ข้างต้น มันเป็นเพียงสามบรรทัด:
from zipfile import ZipFile
path = "dist/my_package-0.0.1a6-py3-none-any.whl"
print('\n'.join(ZipFile(path).namelist()))
ตามที่คาดไว้bdist
ไฟล์ข้อมูลหายไป
_my_data
โฟลเดอร์จะสมบูรณ์หายไป
จะเกิดอะไรขึ้นถ้าฉันสร้าง_my_data/__init__.py
? ฉันทำการทดลองซ้ำและพบว่ายังไม่มีไฟล์ข้อมูลอยู่! รวม
_my_data/
โฟลเดอร์ไว้แต่ไม่มีไฟล์ข้อมูล!
วิธีการแก้
ขัดกับประสบการณ์ของผู้อื่นนี้ไม่ทำงาน:
setuptools.setup(
...
packages=setuptools.find_packages(),
include_package_data=True,
...
)
เมื่อแก้ไขแล้วให้ทำการทดสอบซ้ำ:
$ rm -fr build/ dist/ my_package.egg-info/
$ check-manifest
$ python.exe setup.py sdist bdist_wheel
ตรวจสอบให้แน่ใจว่าsdist
ยังมีไฟล์ข้อมูลอยู่:
$ tar --list -f dist/my_package-0.0.1a6.tar.gz
my_package-0.0.1a6/
...
my_package-0.0.1a6/my_package/__init__.py
my_package-0.0.1a6/my_package/__main__.py
my_package-0.0.1a6/my_package/_my_data/
my_package-0.0.1a6/my_package/_my_data/consola.ttf <-- yay!
my_package-0.0.1a6/my_package/_my_data/icon.png <-- yay!
...
ดูเนื้อหาของbdist
:
$ python check-whl.py
my_package/__init__.py
my_package/__main__.py
my_package/_my_data/consola.ttf <--- yay!
my_package/_my_data/icon.png <--- yay!
my_package-0.0.1a6.dist-info/LICENSE.md
my_package-0.0.1a6.dist-info/METADATA
my_package-0.0.1a6.dist-info/WHEEL
my_package-0.0.1a6.dist-info/entry_points.txt
my_package-0.0.1a6.dist-info/top_level.txt
my_package-0.0.1a6.dist-info/RECORD
วิธีไม่ทดสอบว่ามีไฟล์ข้อมูลหรือไม่
ผมขอแนะนำให้แก้ไขปัญหา / การทดสอบโดยใช้วิธีการที่ระบุไว้ข้างต้นในการตรวจสอบและsdist
bdist
การติดตั้ง pip ในโหมดที่แก้ไขได้ไม่ใช่การทดสอบที่ถูกต้อง
หมายเหตุ: pip install -e .
ไม่แสดงว่าไฟล์ข้อมูลรวมอยู่ในไฟล์bdist
.
ลิงก์สัญลักษณ์ทำให้การติดตั้งทำงานเหมือนกับว่ามีการรวมไฟล์ข้อมูลไว้ (เนื่องจากมีอยู่แล้วในคอมพิวเตอร์ของผู้พัฒนา)
หลังจากนั้นpip install my_package
ไฟล์ข้อมูลจะอยู่ในlib/site-packages/my_package/
โฟลเดอร์ของสภาพแวดล้อมเสมือนโดยใช้โครงสร้างไฟล์เดียวกันกับที่แสดงด้านบนในรายการwhl
เนื้อหา
การเผยแพร่ไปยัง TestPyPI เป็นวิธีทดสอบที่ช้า
การเผยแพร่ไปยัง TestPyPI จากนั้นติดตั้งและค้นหา
lib/site-packages/my_packages
เป็นการทดสอบที่ถูกต้อง แต่ใช้เวลานานเกินไป
data_files
แก้ไขปัญหาด้วยตนเองแล้ว แต่นี่เป็นข้อผิดพลาดได้ง่ายและไม่ "เหมาะสม" สำหรับฉัน มีใครสามารถตรวจสอบได้ว่าจำเป็นต้องทำซ้ำการกำหนดค่าทั้งในpackage_data
และdata_files
หรือไม่