- HPy คือ API ใหม่สำหรับการขยาย Python ด้วยภาษา C
- ใช้
#include <hpy.h> แทน #include <Python.h>
ข้อดีของ HPy
- ไม่มีโอเวอร์เฮดบน CPython: ส่วนขยายที่เขียนด้วย HPy ทำงานได้เร็วเท่ากับส่วนขยายแบบ "ปกติ"
- เร็วกว่าในอิมพลีเมนเทชันทางเลือก: ทำงานได้เร็วขึ้นบน PyPy, GraalPy และอื่น ๆ
- ไบนารีสากล: ส่วนขยายที่บิลด์ด้วย HPy Universal ABI สามารถโหลดได้บน CPython, PyPy, GraalPython และอื่น ๆ โดยไม่ต้องแก้ไข
- เส้นทางการย้ายระบบเพื่อใช้งานร่วมกับ C-API แบบเดิม: สามารถผสมการเรียกใช้ Legacy C-API และ HPy API ได้ เมื่อย้ายโค้ดทั้งหมดเสร็จแล้ว ก็สามารถคอมไพล์เป็นไบนารีสากลที่ทำงานได้บน CPython ทุกเวอร์ชัน, PyPy หรือ GraalPy
- โหมดดีบัก: ช่วยระบุ memory leak, อายุการใช้งานของอ็อบเจ็กต์ที่ไม่ถูกต้อง, การใช้ API ผิดวิธี และอื่น ๆ ได้ง่าย
- API ที่ดีกว่า: ออกแบบมาเพื่อก้าวข้ามข้อจำกัดของ Python/C API มาตรฐาน สร้างส่วนขยายที่มีความสม่ำเสมอและคุณภาพดีกว่า และทำให้เกิดบั๊กได้ยากขึ้น
- ความสามารถในการพัฒนาต่อ: ตามที่สรุปไว้อย่างดีใน PEP 620 นั้น Python/C API มาตรฐานเปิดเผยรายละเอียดการทำงานภายในจำนวนมาก ทำให้การพัฒนา C API ต่อทำได้ยาก HPy ซ่อนรายละเอียดภายในทั้งหมด จึงไม่มีปัญหานี้
สถานะปัจจุบัน
- HPy ยังอยู่ระหว่างการพัฒนาอย่างต่อเนื่อง โดย 0.9.0 เป็น alpha release ล่าสุด แต่คาดว่าจะพ้นสถานะ alpha ในไม่ช้า และกำลังมุ่งสู่ stable release
- ทีมงานมองว่า HPy ABI มีความเสถียรมากพอแล้วที่จะรักษาคำมั่นเรื่องความเข้ากันได้ของไบนารีทั้งย้อนหลังและล่วงหน้าในรีลีสถัด ๆ ไป
- เชื่อว่า API ตอนนี้รองรับกรณีใช้งานได้มากพอสำหรับการย้ายแพ็กเกจสำคัญแล้ว (โดยเฉพาะดูที่การพอร์ต numpy)
- มีทั้งคู่มือการพอร์ตและเอกสารประกอบอย่างครอบคลุม (โดยเฉพาะ API reference) ให้ใช้งาน
- เปิดรับการพูดคุยด้านการออกแบบและความต้องการใหม่ ๆ อยู่เสมอ
ส่วนขยายที่รองรับ HPy
- ultrajson-hpy: โมดูลใช้งานจริงตัวแรกที่ถูกพอร์ตไปยัง HPy
- piconumpy: ตามชื่อเลย เป็นโมดูลคล้าย numpy แบบมินิมัลสำหรับกำหนดชนิดข้อมูลแบบกำหนดเอง
- numpy: หนึ่งในเป้าหมายที่ทะเยอทะยานคือการพอร์ต numpy ไปยัง HPy และใช้ประสบการณ์นี้เพื่อทำความเข้าใจการออกแบบ API ให้ดียิ่งขึ้น โดยพอร์ตนี้ใกล้จะผ่าน test suite แล้ว
- matplotlib: เนื่องจากยังมีการพึ่งพา NumPy อยู่ การย้ายไปสู่โหมดสากลจึงยังไม่สมบูรณ์ทั้งหมด HPy มี legacy compatibility API เพื่อให้ยังสามารถเรียกใช้ฟังก์ชัน Legacy C API และรัน test suite ได้สำเร็จ
- kiwi-solver: dependency ของ Matplotlib ที่พอร์ตสู่โหมดสากลได้สมบูรณ์แล้ว
ความเห็นของ GN⁺
- HPy เป็นโครงการที่มีอนาคตไกลมาก เพราะช่วยก้าวข้ามข้อจำกัดของ Python/C API และมอบความสามารถในการขยายและการพกพาที่ดีกว่า
- จุดที่น่าสนใจเป็นพิเศษคือศักยภาพในการเพิ่มประสิทธิภาพบน Python implementation ทางเลือกอย่าง PyPy และ GraalPy
- แม้การย้ายจาก Legacy C API อาจเป็นเรื่องยาก แต่ HPy มีเส้นทางการย้ายแบบค่อยเป็นค่อยไป ทำให้กระบวนการนี้จัดการได้ง่ายขึ้นมาก
- เมื่อต้องการนำ HPy ไปใช้ ควรพิจารณาการผสานเข้ากับระบบบิลด์และ pipeline การแจกจ่ายเดิม การยอมรับจากโครงการต้นน้ำ รวมถึงระดับความสมบูรณ์และเสถียรภาพของ HPy เอง
- โครงการอื่นที่มีเป้าหมายคล้ายกับ HPy ได้แก่ Cython และ PyO3 ของ Rust ซึ่งต่างจาก HPy ตรงที่ใช้ภาษาระดับสูงแทน C API ระดับต่ำ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ส่วนที่น่าปวดหัวที่สุดของการทำงานกับ C API คือการตั้งค่าแฟล็กคอมไพล์/ลิงก์
python3-configใช้งานได้เฉพาะในระดับ OS และใช้งานลำบากเมื่อต้องเข้าถึงแพ็กเกจที่ติดตั้งผ่าน pippython3 -m venvไม่ได้สร้างสคริปต์เหล่านี้ และ anaconda/miniconda ก็มีปัญหาเช่นกัน แต่ละแพ็กเกจทำให้สคริปต์บิลด์สกปรกด้วยการเรียกแบบฮาร์ดโค้ดpython3 -c "import sys: print..."ได้เปิด PR เพื่อเพิ่มแฟล็กpython3 -m sysconfig --jsonให้กับ CPythonการที่ภาษา Python มุ่งเน้นไปที่อิมพลีเมนเทชันเดียวมากเกินไป อาจเป็นภัยต่อความสำเร็จในระยะยาว เว็บเซิร์ฟเวอร์ โปรแกรมบรรทัดคำสั่ง และอุปกรณ์ฝังตัว ต่างก็มีความต้องการที่ต่างกัน หากโปรเจ็กต์นี้สำเร็จในการแทนที่ C API ของ Python ด้วยสิ่งที่ไม่เปิดเผยรายละเอียดการอิมพลีเมนต์ ก็อาจทำให้การดูแลอิมพลีเมนเทชันทางเลือกและการทดลองเทคโนโลยีใหม่ ๆ ง่ายขึ้น
สงสัยว่าโปรเจ็กต์นี้ให้ Python bindings ที่ไม่ผูกกับเวอร์ชันหรือไม่ ตอนนี้ต้องบิลด์ bindings แยกสำหรับแต่ละเวอร์ชันอยู่ และนั่นกินเวลา CI/CD ไปมาก
น่าจะน่าสนใจถ้ามีเบนช์มาร์กระหว่างส่วนขยาย HPy กับการใช้งาน Cython/pybind11 ทั้งในแง่ประสิทธิภาพและเวลาในการพัฒนา
ยังไม่ชัดเจนว่าโปรเจ็กต์นี้ทำงานร่วมกับไลบรารีอย่าง PyBind11 หรือ nanobind อย่างไร ดูเหมือนว่าถ้าจะใช้งานไลบรารีเหล่านี้แบบเดิม ก็คงต้องเขียนใหม่
สงสัยว่าทุกวันนี้ยังมีส่วนขยายใหม่ที่เขียนด้วย C มากแค่ไหน เดิมคิดว่าส่วนใหญ่คงเป็นพวก Boost Python, pybind, PyO3
มักโพสต์เกี่ยวกับการทำ CPython bindings โดยมีโอเวอร์เฮดต่ำที่สุด และอยากแชร์คำแนะนำ คำถาม และข้อกังวลบางอย่าง น่าจะดีถ้าปรับโครงสร้างหน้า landing page และ README ในรีโพซิทอรีของโปรเจ็กต์ HPy ใหม่ ถ้ามีสถิติการรองรับสำหรับ PyPy, GraalPython และ Python runtime อื่น ๆ ก็จะน่าเชื่อถือยิ่งขึ้น
การใช้คอนเท็กซ์อ็อบเจ็กต์แบบห่อหุ้มอย่าง
HPyContextมีประโยชน์สำหรับอนาคตของ Python แบบมัลติเธรดหรือในสภาพแวดล้อมที่ซับซ้อน แต่ถ้าHPyContextถูกรีไดเร็กต์ไปยังซิงเกิลตันของ CPython ก็จะไม่ได้แก้ปัญหาเบนช์มาร์กจากปี 2019 กล่าวถึงกฎการเรียก
METH_FASTCALLของ CPython แต่ไม่ได้เปรียบเทียบกัน ถ้าสนใจเรื่องประสิทธิภาพ ก็ควรพาร์สอาร์กิวเมนต์จากทูเพิลโดยตรงแทนการใช้ตัวจัดรูปแบบสตริงสงสัยว่าใน Python มีอะไรที่เรียบง่ายแบบ ffi ของ luajit หรือไม่ ที่ให้ C headers มาแล้วโหลด shared library เพื่อใช้งาน struct และเรียกฟังก์ชันได้
สนใจการเรียก Go จาก Python และ gopy สร้าง Python bindings สำหรับ cgo อยู่แล้ว HPy<->cgo อาจมีโอเวอร์เฮดน้อยกว่า
อยากให้ลองนึกภาพว่าถ้างานนี้เสร็จสิ้นไปตั้งแต่เมื่อ 20 ปีก่อน ระบบนิเวศของ Python จะต่างออกไปแค่ไหน