• uv ที่ลองใช้มา 1 ปีในหลายสภาพแวดล้อมของลูกค้า ช่วยทำให้การเริ่มโปรเจกต์ Python และการจัดการ dependency ง่ายขึ้นมาก จึงคุ้มค่าที่จะลองก่อนในสภาพแวดล้อมที่ทำได้
  • ยังคง เวิร์กโฟลว์ pip/venv เดิมไว้ได้แทบทั้งหมด แต่ทำงานได้เร็วและเสถียรกว่า ทำให้ต้นทุนการย้ายระบบค่อนข้างต่ำ
  • รวมการติดตั้ง Python, virtual environment, lock file, การรัน, การ build และการรันเครื่องมือชั่วคราวไว้ในเครื่องมือเดียว ช่วยลด ต้นทุนการทดลองโปรเจกต์ ได้มาก
  • อย่างไรก็ตาม ข้อจำกัดที่เกิดขึ้นจริงยังมีอยู่ เช่น การ resolve dependency ของระบบ legacy ล้มเหลว, ขอบเขตการรองรับของ python-build-standalone, cache ที่อาจโตเกิน 20GB, นโยบายความปลอดภัยขององค์กร และกำแพงด้าน CLI
  • หากยังทำงานกับ Python ต่อไป แม้จะใช้ uv ก็ยังจำเป็นต้องรู้จัก pip และ venv เพื่อเตรียมพร้อมสำหรับสภาพแวดล้อมที่ไม่อนุญาตให้ใช้ uv หรือไม่เหมาะกับ uv

จุดเริ่มต้นที่ทำให้โปรเจกต์ Python ยากขึ้น

  • รากของปัญหาใหญ่ที่สุดใน Python อยู่ที่ การ bootstrap คือการเตรียม Python เองและเริ่มโปรเจกต์ใหม่
  • ปัญหา packaging จำนวนมากที่พบภายหลัง ก็ไม่ได้มาจากการติดตั้ง dependency หรือการ build package โดยตรงเท่านั้น แต่มาจากการติดตั้ง Python และการตั้งค่าโปรเจกต์ในช่วงแรก
  • วิธีติดตั้ง Python แตกต่างกันไปตาม OS และค่า default กับกับดักต่าง ๆ ก็ไม่เหมือนกัน
  • แม้ Python จะเป็นภาษาที่เหมาะกับผู้เริ่มต้น แต่การติดตั้ง Python กลับต้องมีความรู้พื้นฐานล่วงหน้าค่อนข้างมาก
  • Python ถูกใช้โดยกลุ่มคนที่หลากหลายมาก เช่น นักเรียน นักวิทยาศาสตร์ข้อมูล นักพัฒนา AI นักพัฒนาเว็บ ผู้ดูแลระบบ นักชีววิทยา นักภูมิศาสตร์ และนักพัฒนา plugin
  • สภาพแวดล้อมที่รันแตกต่างกันมาก ตั้งแต่เครื่อง Windows ของบริษัท, โน้ตบุ๊ก Debian ส่วนตัว, มหาวิทยาลัย, หน่วยงานรัฐ, startup, กองทัพ, สถาบันวิจัย ไปจนถึงองค์กรขนาดใหญ่ ทำให้ tutorial เดียวครอบคลุมทุกคนได้ยาก
  • PATH, PYTHONPATH, การมี Python หลายเวอร์ชันร่วมกัน, package ทางเลือกบน Linux, Python ในฐานะ system dependency และความนิยมของ compiled extension ล้วนเพิ่มความซับซ้อน
  • เครื่องมือจัดการโปรเจกต์ Python ที่ดีควรมีเงื่อนไขต่อไปนี้
    • ต้องทำงานได้อย่างเป็นอิสระจากการ bootstrap Python
    • ต้องทำให้การติดตั้งและรัน Python เป็นหนึ่งเดียวกันข้าม platform และสถานการณ์ต่าง ๆ
    • ต้องทำหน้าที่เป็นสะพานเชื่อมกับเครื่องมือพื้นฐานอย่าง pip และ venv
    • ต้องมี dependency resolver ที่แข็งแกร่ง
    • ต้องจัดการงานติดตั้งง่าย ๆ ได้อย่างสะดวก และทำงานซับซ้อนได้ด้วย เช่น การติดตั้ง dependency ที่ lock ไว้จาก OS อื่น
    • ต้องติดตั้งและใช้งานง่าย และน่าเชื่อถือพอที่จะฝากส่วนสำคัญของ stack ไว้ได้

วิธี bootstrap ของ uv

  • uv ติดตั้งและอัปเดตได้อย่างเป็นอิสระจาก Python โดยสมบูรณ์ การติดตั้ง uv กับการติดตั้ง Python จึงไม่กระทบกัน
  • ปัญหา bootstrap ของ Python, ปัญหา PATH และปัญหา import ไม่ส่งผลต่อ uv เอง
  • ลดความสับสน เช่น ควรติดตั้งไว้ในระบบหรือใน virtual environment หรือ keyword ใหม่กับสิ่งที่ถูกเลิกใช้จะส่งผลต่อ uv อย่างไร
  • uv เริ่มจากการ提供 interface ของ pip และ venv เพื่อให้ใช้ร่วมกับโปรเจกต์ เครื่องมือ และวิธีคิดเดิมได้
    • เป็นทางเลือกที่คำนึงถึง community เดิมและ legacy code
    • ผู้ใช้สามารถใช้งานเหมือนเวิร์กโฟลว์ pip·venv เดิมได้ โดยไม่ต้องเรียนรู้ uv run, uv add, uvx
    • แค่ความเร็วและความน่าเชื่อถือที่ได้จากงานพื้นฐาน ก็เป็นเหตุผลให้ย้ายมาใช้แล้ว
  • ยังมีฟังก์ชันติดตั้ง Python ด้วย
    • ติดตั้งด้วยวิธีเดียวกันบนทุก OS
    • ไม่ต้องใช้สิทธิ์ผู้ดูแลระบบ
    • ทำงานแยกจาก system Python
    • ติดตั้งหลายเวอร์ชันได้โดยไม่ชนกัน
    • ให้ standard library ชุดเดียวกัน และรวม tkinter ไว้ด้วย
    • รวมเวอร์ชัน Pypy, No-GIL และ TCO ด้วย
    • ทำงานโดยไม่ต้องใช้ shim, การ compile หรือค่า default ที่ไม่สมเหตุสมผล

ประสบการณ์ติดตั้ง Python และ python-build-standalone

  • ตัวอย่าง uv python install pypy3.8 ติดตั้ง Python 3.8.16 ได้ภายใน 2.71 วินาที
  • สามารถรันด้วยวิธีเดียวกันบน Mac หรือ Windows ได้
  • ไม่มีปัญหา package ที่หายเกี่ยวกับ Tcl, OpenSSL, Gzip, การชนกับแหล่งติดตั้ง Python อื่น, paradigm ที่ต่างกันตาม OS, command ที่หายไป หรือ PATH ที่ตั้งค่าผิด
  • การติดตั้ง Python ของ uv ใช้ python-build-standalone และ Astral ได้เข้ามารับช่วงโปรเจกต์นี้เพื่อปรับปรุงต่อ
  • Astral พยายามส่งคืนข้อดีเหล่านี้กลับไปยัง upstream project ของ cPython และเคย contribute ให้ open source project ใกล้เคียงด้วย

ฟังก์ชันจัดการโปรเจกต์

  • uv init โดย default จะสร้าง .venv, pyproject.toml, git repository ที่มี .gitignore สำหรับ Python, README.md และ hello.py
  • สามารถประกาศ root dependency ใน pyproject.toml หรือเพิ่มด้วย uv add ได้
  • uv remove จะจัดระเบียบ repository ให้ถูกต้อง
  • uv lock --upgrade-package <package>==<version> ช่วยให้อัปเกรด package ทีละเวอร์ชันอย่างระมัดระวังได้
  • uv build สร้าง package .whl จากโปรเจกต์ แต่ uv ไม่ได้บังคับว่าโปรเจกต์ต้อง build ได้เสมอ
  • uv run รัน command ภายใน virtual environment ได้ แม้ virtual environment จะไม่ได้ถูก activate
    • ผู้ใช้ไม่จำเป็นต้องรู้ว่ามี virtual environment อยู่หรือเข้าใจแนวคิดการ activate
  • command เหล่านี้อัปเดต lock file ให้โดยอัตโนมัติและโปร่งใส
    • เพราะ uv เร็วมาก จึงแทบไม่รู้สึกว่ามีการอัปเดตเกิดขึ้น
    • ผู้ใช้ไม่จำเป็นต้องรู้ว่า lock file คืออะไร
  • lock file เป็นแบบ cross-platform จึงพัฒนาบน Windows แล้ว deploy ไป Linux ได้

ประสิทธิภาพ ความเสถียร และข้อความ error

  • ประสิทธิภาพของ uv ลดต้นทุนในการติดตั้ง dependency และการทดลองโปรเจกต์
  • เริ่มใหม่ได้อย่างรวดเร็ว จึงลองหลายแนวทางซ้ำ ๆ ได้โดยไม่เป็นภาระ
  • เครื่องมืออย่าง pyenv, pipenv, poetry เคยพังพร้อม stack trace ในหลายสภาพแวดล้อม แต่ uv ทำงานได้แข็งแรงมาก
  • ด้านคุณภาพของ Astral มีสามเรื่องที่โดดเด่นเป็นพิเศษ
    • แก้ bug เร็ว และตอบสนองต่อ feedback กับ report ดี
    • มีวัฒนธรรมการทดสอบที่แข็งแรง และให้ dependency resolution test suite เป็น package แยกต่างหาก
    • ข้อความ error ดีมาก
  • ตัวอย่าง uv add httpie==2 แสดงทีละขั้นว่า httpie==2.0.0 พึ่งพา requests>=2.22.0 แต่โปรเจกต์พึ่งพา requests==1 จึงไม่สามารถทำตาม requirement ได้
  • ข้อความ error ของการ resolve dependency ได้รับอิทธิพลจาก pubgrub ด้วย แต่ข้อความ error ทั่วทั้ง uv ก็เป็นไปในแนวทางเดียวกัน
  • เมื่อใช้ uv ในการสอน นักศึกษาสามารถใช้งานได้อย่าง productive โดยแทบไม่ต้องเข้าไปช่วยมาก ซึ่งไม่เคยได้ประสบการณ์แบบนี้กับเครื่องมืออื่น
  • โปรเจกต์ใหม่ที่เป็นงานมืออาชีพได้รับประโยชน์จาก uv ได้ง่าย แต่ในโปรเจกต์ legacy อาจมีสิ่งที่ขวางอยู่

uvx และวิธีใช้งานรูปแบบใหม่

  • uv ให้ building block ที่แข็งแรงและรวดเร็วสำหรับการเตรียมและแยก Python กับ dependency
  • ก่อนหน้านี้ การเตรียม Python และ dependency เป็นข้อจำกัดที่ช้าและอาจพังได้ แต่ใน uv สามารถมองเป็น ฟีเจอร์ ที่ใช้ปรับเวิร์กโฟลว์ได้
  • uv run --with jupyter jupyter notebook รัน Jupyter ในโปรเจกต์ปัจจุบัน แต่ไม่เพิ่ม Jupyter และ dependency ของมันเข้าไปในโปรเจกต์
  • uvx --with pendulum -p 3.13t python ดาวน์โหลดและติดตั้ง build ใหม่ของ Python No-GIL, สร้าง virtual environment ชั่วคราว, ติดตั้ง pendulum แล้วเปิด Python shell
  • uvx เป็นเครื่องมือคล้าย npx สำหรับ Python และมองได้ว่าเป็นรูปแบบที่ทำ pipx ออกมาอย่างถูกต้อง
  • การรองรับ inline dependency เปลี่ยนวิธีใช้ dependency ในสคริปต์ Python ขนาดเล็ก
    • ก่อนหน้านี้ ในสคริปต์เล็ก ๆ มักต้องหลีกเลี่ยง dependency หรือใช้ workaround ที่ยุ่งยาก
    • ตอนนี้สามารถใช้ dependency ได้อย่างรวดเร็ว โปร่งใส และอธิบายตัวเองได้
  • ฟีเจอร์เหล่านี้ไม่ได้ถูกบังคับ ผู้ใช้จึงค่อยค้นพบและนำมาใช้เมื่อจำเป็นได้

จุดที่ uv ล้มเหลวหรือใช้งานไม่สะดวก

  • uv ไม่สามารถแก้ปัญหา packaging จริงแทนได้
    • ปัญหาอย่าง version marker ที่ผิด, ไม่มี wheel, ชื่อชนกัน อยู่นอกการควบคุมของ uv
    • ปัญหาเหล่านี้ฝังอยู่ในคุณภาพข้อมูลบน PyPI
    • เหตุผลที่ปัญหา packaging ดูลดลงเมื่อใช้ uv คือ uv จัดการส่วนอื่นได้ถูกต้อง
  • dependency resolver ที่เข้มงวดกว่าอาจทำให้ virtual environment ของโปรเจกต์ legacy ที่เคยพึ่งพาการ resolve แบบหลวม ๆ ของ pip รุ่นเก่าพังได้
    • ในกรณีหนึ่ง codebase อายุ 15 ปีเพิ่งถูก migrate ไป Python 3 และตั้งอยู่บนประวัติ pip freeze ที่ไม่ได้จัดระเบียบ uv จึงทำงานไม่ได้
  • การติดตั้ง Python ในตัวของ uv จำกัดอยู่กับเวอร์ชันที่ build ด้วย python-build-standalone
    • installer จาก python.org, deadsnake และ pyenv สามารถติดตั้ง Python ได้มากกว่าเวอร์ชัน
    • อาจเป็นปัญหาสำหรับโปรเจกต์เก่าที่จำเป็นต้องใช้ Python เวอร์ชันเฉพาะ
    • uv ทำงานร่วมกับ Python ที่ติดตั้งจากภายนอกได้ดี จึงไม่ใช่สิ่งที่ปิดทางอย่างสมบูรณ์
  • executable ของ python-build-standalone อาจช้ากว่าเล็กน้อย
    • ตาม pyperformance นั้น 3.10 ของ uv ช้ากว่า Python ของ Ubuntu อยู่ 3%
    • อาจมีคนต้องการใช้ Python ที่ compile พร้อม optimization สำหรับ hardware
  • พื้นที่ cache ก็อาจเป็นข้อเสียได้
    • หลังใช้งาน 1 ปี cache ของ uv ใช้พื้นที่บนดิสก์ มากกว่า 20GB
    • ลบได้ด้วย uv cache clean แต่จะเสียข้อได้เปรียบด้านความเร็ว
    • ต่างจาก pip ตรงที่ uv ใช้ hard link package ให้กินพื้นที่เพียงครั้งเดียว จึงอาจใช้พื้นที่น้อยกว่า virtual environment หลายชุดแบบเดิมทั้งหมด
  • $UV_PYTHON มีความไม่สะดวกตรงที่บังคับเวอร์ชัน Python แทนที่จะให้เวอร์ชัน default และ issue ที่เกี่ยวข้องกำลังอยู่ระหว่างจัดการ
  • uv เป็น open source แต่เป็นผลิตภัณฑ์ของบริษัทเชิงพาณิชย์ Astral
    • Astral ยังไม่ทำกำไร และยังไม่ได้เปิดตัวผลิตภัณฑ์เชิงพาณิชย์
    • มีความเห็นว่าควรระมัดระวังก่อนฝากส่วนสำคัญของ stack ไว้กับมัน
    • ในทางกลับกัน ต้นทุนการย้ายไป uv และต้นทุนการย้ายออกจาก uv ก็ต่ำ
  • ข้อจำกัดใหญ่ที่สุดคือการนำไปใช้ในองค์กร
    • ในสภาพแวดล้อมขององค์กรขนาดใหญ่ที่มีความปลอดภัยสูงและถูก lock ไว้ การติดตั้ง dependency ใหม่ทำได้ยากมาก
    • หากฝ่าย IT security ควบคุมสิ่งที่ทำได้บนเครื่อง อาจไม่อนุญาตให้ติดตั้ง uv
    • จนกว่าจะถึง stable version และตอบโจทย์หลาย requirement ได้ครบ สภาพแวดล้อมองค์กรยังมีข้อจำกัดมาก
  • CLI ก็เป็นกำแพงเช่นกัน
    • ผู้ใช้ Python ที่ไม่คุ้นกับ command line มีไม่น้อย โดยเฉพาะผู้ใช้ Windows
    • นี่ก็เป็นหนึ่งในเหตุผลที่ Anaconda มี GUI
    • การต้องใช้เครื่องมือ CLI สำหรับมือใหม่โดยสมบูรณ์เป็นกำแพงเข้าสู่การใช้งาน
  • uvx และ uv tool install ชวนให้ติดตั้งเครื่องมือไว้นอกโปรเจกต์เหมือน pipx
    • เหมาะกับเครื่องมือ standalone อย่าง yt-dlp, httpie
    • แต่เครื่องมือพัฒนาอย่าง mypy ที่อ่อนไหวต่อเวอร์ชัน Python หรือ syntax ของ library อาจเกิดปัญหาได้ หากติดตั้งอยู่กับ Python คนละเวอร์ชันกับโปรเจกต์

เมื่อใดควรหลีกเลี่ยง uv

  • มี 5 สถานการณ์ที่ไม่ควรใช้ uv
    • มีโปรเจกต์ legacy ที่ทำงานไม่ได้กับ dependency resolver ของ uv และไม่มีแรงหรือไม่ต้องการจัดระเบียบเพื่อ migrate
    • สภาพแวดล้อมองค์กรไม่อนุญาตให้ใช้ uv
    • ไม่ไว้วางใจเพราะ uv ยังไม่ใช่ stable version, ผลิตภัณฑ์เชิงพาณิชย์ของ Astral ยังไม่ออก หรือกลุ่ม contributor ภาษา Rust ยังเล็ก
    • ต้องการ Python เวอร์ชันเฉพาะที่ uv ไม่มีให้ และไม่อยากใช้ uv ร่วมกับ Python ที่ติดตั้งจากภายนอก
    • CLI เป็นอุปสรรคใหญ่เกินไปสำหรับทีม
  • ปัญหาเรื่องความไว้วางใจและ Python เวอร์ชันเฉพาะเป็นเรื่องของการเลือกมากกว่าการถูกบล็อกทางเทคนิค
  • ข้อจำกัดของสภาพแวดล้อมองค์กรเป็นสิ่งที่ผู้ใช้ทำอะไรได้ไม่มาก
  • ประเด็นสำคัญที่ต้องพิจารณาจริง ๆ คือ legacy dependency และกำแพงด้าน CLI
  • คำแนะนำเรียบง่ายคือ
    • ลองใช้ uv ก่อนเสมอ
    • ถ้าใช้ไม่ได้ ให้กลับไปใช้วิธีเดิมหรือหา workaround
  • หาก CLI เป็นปัญหา อาจใช้ installer จาก python.org สำหรับเตรียม Python และเสนอ IDE plugin ที่ห่อ uv ไว้อีกชั้น
  • คนที่เขียนโปรแกรมได้มีแนวโน้มจะเรียนรู้พื้นฐาน command line ที่จำเป็นต่อการใช้ uv ได้

ตำแหน่งในอนาคต

  • หากต้องการใช้ในองค์กร ยังมีช่องว่างก่อนถึง v1 และสำหรับองค์กรที่อัปเดตบ่อยได้ยาก stable version จึงสำคัญ
  • คาดว่าอาจเพิ่มฟังก์ชัน bundling ที่เป็นทางเลือกแทน pex/shiv และ build backend
  • ฟังก์ชันสร้าง installer สำหรับ application ดูเป็นบทสรุปที่สมเหตุสมผล แต่ซับซ้อนกว่ามาก เพราะแค่การ signing ให้ถูกต้องก็ยากแล้ว
  • เมื่อ task support ถูกจัดระเบียบแล้ว ฟีเจอร์จะเพียงพอสำหรับความต้องการส่วนตัว
  • หาก Python เป็นอาชีพ ก็ยังควรเรียนรู้วิธีใช้ pip และ venv
    • เพราะสักวันหนึ่งอาจเจอสถานการณ์ที่ใช้ uv ไม่ได้
  • โดยสรุป uv มีต้นทุนต่ำและให้ประโยชน์สูง จึงเป็น แนวทางแบบ Pareto ที่ควรลองก่อนในสภาพแวดล้อมที่ใช้งานได้

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น