14 คะแนน โดย GN⁺ 2025-06-25 | 2 ความคิดเห็น | แชร์ทาง WhatsApp
  • ตัวจัดการแพ็กเกจ uv และ PEP 723 ช่วยให้สามารถรันสคริปต์ Python ได้โดยไม่ต้องกังวลเรื่อง dependency
  • ฟีเจอร์ uvx จะสร้าง virtual environment แบบชั่วคราวให้อัตโนมัติ ช่วยแก้ปัญหาความยุ่งยากในการตั้งค่าสภาพแวดล้อม
  • หากใส่ เมทาดาทา PEP 723 ไว้ในไฟล์ Python จะช่วยให้การรันสคริปต์และการจัดการแพ็กเกจเป็นไปโดยอัตโนมัติและสะดวกขึ้น
  • มี ตัวอย่างสคริปต์ใช้งานจริง ที่สามารถนำไปสร้างและแจกจ่ายโปรแกรมดึงคำบรรยาย YouTube ได้อย่างรวดเร็ว
  • ทำให้ตอนนี้ Python ก็สามารถ เขียนไฟล์รันเดี่ยวแบบกระชับ ได้แล้ว และเพิ่มความคล่องตัวในการใช้งานสคริปต์อย่างมาก

ภาพรวม

  • เดิมทีการรัน "สคริปต์ใช้ครั้งเดียว (one-off script)" ใน Python มักต้องตั้งค่าสภาพแวดล้อมและติดตั้งแพ็กเกจใหม่ทุกครั้ง แต่เมื่อมี uv และ PEP 723 ปัญหานี้ก็แทบหมดไป
  • uv คือ ตัวจัดการแพ็กเกจและโปรเจกต์ Python ความเร็วสูง ที่พัฒนาด้วย Rust และมีฟีเจอร์ใหม่อย่าง uvx ซึ่งช่วยจัดการ virtual environment แบบชั่วคราว การติดตั้งแพ็กเกจอัตโนมัติ และการผูกกับเวอร์ชัน Python ได้อย่างรวดเร็วและง่ายมาก

ข้อดีของ uv และ uvx

  • ฟีเจอร์ uvx ทำงานคล้าย npx ใน ecosystem ของ Nodejs โดยจะสร้างสภาพแวดล้อมสำหรับรันแพ็กเกจ Python ที่ระบุไว้ (เช่น ruff) ได้อย่างรวดเร็ว
  • ใช้ disposable virtual environment ผ่านระบบแคช จึงรันได้รวดเร็วโดยแทบไม่มี overhead
  • การตั้งค่าสภาพแวดล้อมและติดตั้ง dependency ทำได้ด้วยคำสั่งบรรทัดเดียว ทำให้นักพัฒนาไม่ต้องดูแลการตั้งค่าสภาพแวดล้อมแยกต่างหาก

แนะนำ PEP 723 และการใช้งาน

  • PEP 723 เป็นมาตรฐานที่กำหนดให้สามารถใส่ เมทาดาทาด้าน dependency และสภาพแวดล้อม ไว้ที่ส่วนบนของสคริปต์ Python ได้
  • ตัวอย่างเช่น สามารถระบุ requires-python, dependencies เป็นต้น ไว้ที่ด้านบนของโค้ดได้
  • เครื่องมือภายนอกที่รองรับข้อมูลนี้ (เช่น uv) จะใช้ข้อมูลในไฟล์สคริปต์เพื่อติดตั้งแพ็กเกจ ตั้งค่าสภาพแวดล้อม และรันโปรแกรมให้อัตโนมัติ
โฆษณา

การผสาน uv กับ PEP 723

  • ในตัวอย่างจริง เมื่อนำเมทาดาทานี้ไปเขียนไว้ด้านบนของไฟล์ Python แล้วรันด้วยคำสั่ง uv run ระบบจะติดตั้งแพ็กเกจที่จำเป็นทั้งหมด ตั้งค่าเวอร์ชัน Python ตามที่กำหนด และรันโค้ดทันที
  • โค้ดตัวอย่างจะเรียกใช้งาน API บนอินเทอร์เน็ต (รายการ PEP) และแสดงผลลัพธ์ โดยไม่ต้องติดตั้งแพ็กเกจเพิ่มเติมหรือตั้งค่าสภาพแวดล้อมเอง สามารถรันได้ด้วยคำสั่งบรรทัดเดียว

ตัวอย่างการใช้งานจริง: สคริปต์คำบรรยาย YouTube

  • มีตัวอย่างสคริปต์ Python ที่เพิ่ม shebang(#!/usr/bin/env -S uv run --script) และเมทาดาทา PEP 723
  • รองรับการติดตั้งแพ็กเกจภายนอกอย่าง youtube-transcript-api อัตโนมัติ พร้อมตั้งค่า virtual environment ให้อัตโนมัติ
  • ผู้ใช้สามารถส่ง URL หรือ ID ของวิดีโอ YouTube เป็นอาร์กิวเมนต์ให้ไฟล์รัน (ytt) เพื่อดึงคำบรรยายและรับผลลัพธ์ได้ทันที
  • หลังให้สิทธิ์รันด้วย chmod แล้ว ก็สามารถเรียกใช้งานจากเทอร์มินัลได้อย่างง่ายดาย

ประสบการณ์นักพัฒนาที่ดีขึ้นและการขยายขอบเขตการใช้งาน

  • ในอดีต แม้แต่การรันสคริปต์ง่าย ๆ ผู้ใช้ก็มักเอนเอียงไปหา Go หรือภาษาแบบไบนารีไฟล์เดี่ยวมากกว่า แต่ตอนนี้ Python ก็ให้ความสะดวกในระดับใกล้เคียงกันได้แล้ว
  • การผสาน uv กับ PEP 723 ทำให้การแชร์ การแจกจ่าย และการทำงานอัตโนมัติของสคริปต์ Python ง่ายขึ้นอย่างมาก
  • มีตัวอย่างบน GitHub (cottongeeks/ytt-mcp) ที่สามารถนำไปต่อยอดสู่กรณีใช้งานที่ซับซ้อนยิ่งขึ้นได้

2 ความคิดเห็น

 
ndrgrd 2025-06-25

uv เร็วมากจริง ๆ เลยชอบมากครับ/ค่ะ ช่วงนี้ก็เลยใช้ uv ทุกที่ที่เป็นไปได้

 
GN⁺ 2025-06-25
ความคิดเห็นจาก Hacker News
  • ช่วงนี้ก็เหมือนผู้เขียน คือหยิบ Python แบบครอสแพลตฟอร์มสำหรับงาน one-off และสคริปต์ส่วนตัวมาใช้บ่อยกว่า Go แต่ก็ยังไม่ค่อยพอใจกับสภาพของระบบตรวจเช็ก type ของ Python ที่ยังสับสนสุด ๆ หวังว่าเครื่องมืออย่าง ty, pyrefly จะช่วยให้ดีขึ้นได้บ้าง

  • ตอนนี้รู้สึกว่าสคริปต์ Python ใช้งานได้ลื่นเลยโดยไม่ต้องทุกข์กับ virtualenv อีกต่อไป เลยคิดว่าน่าจะดีถ้าฝั่ง shell script ก็มีประสบการณ์แบบนี้บ้าง เรื่อง packaging, การจัดการ dependency และ reproducibility ยังเหมือนอยู่ในยุคหิน ตอนนี้ก็ยังมีแค่ทางเลือกแบบ curl | bash แล้วลุ้นเอาเอง หรือไม่ก็ README ที่บอกให้ติดตั้ง dependency ที่ขาดอีก 3 ตัวพร้อมขั้นตอน manual 12 ขั้น Nix? ให้ความรู้สึกว่าเป็นตัวเลือกที่ใช้ได้เฉพาะคนที่ก้าวข้ามเวลา พื้นที่ และคู่มือ Nix ไปแล้วเท่านั้น Docker? ถ้าคุณคิดว่าการดาวน์โหลด Linux distribution มาเพื่อรัน sed แค่ครั้งเดียวเป็นเรื่องสมเหตุสมผล ก็โอเคเลย น่าจะต้องมีจุดกึ่งกลางที่เรียบง่าย เป็นแบบ declarative และใครก็ใช้ได้จริง

    • ส่วนตัวชอบเขียนเฉพาะ shell script ที่ใช้แค่ binary และ library ที่มีมาใน OS เป้าหมายอยู่แล้ว เป้าหมายที่จะทำให้ shell script พกพาได้จริง ๆ เป็นทางเลือกที่ไม่ค่อยเข้ากันในเชิงปฏิบัติ ถ้าต้องเอา shell script ที่ใช้คำสั่งเฉพาะของ macOS ไปรันบน Linux นี่เป็นปัญหาที่ package manager ไหนก็แก้ไม่ได้
    • Nix สำหรับจุดประสงค์นี้จริง ๆ แล้วไม่ได้ใช้งานยากขนาดนั้น ถ้าติดตั้ง Nix บนดิสโทรอื่นก็ใช้งานง่ายประมาณนี้ได้ ตัว NixOS หรือโลกของการแพ็กเกจบน Nix ทั้งหมดอาจท้าทายพอสมควร แต่ถ้าจำกัดแค่กับ shell script ก็ถือว่าเริ่มต้นได้ไม่ยาก
    • ไม่ค่อยรู้สึกว่าจำเป็นต้องเขียน shell script ใหม่ ๆ แล้ว ถ้าอยู่ในสภาพแวดล้อมที่อนุญาตให้ติดตั้ง dependency ทั้งหมดได้ เครื่องมืออย่าง uv ก็จัดการให้หมด ถ้าชอบ Clojure ก็แนะนำ babashka ด้วย
    • ที่เรื่อง packaging, การจัดการ dependency และ reproducibility ใน shell script ดูโบราณ ก็เพราะถ้าคุณต้องการสิ่งเหล่านี้มากถึงระดับนั้น shell อาจไม่ใช่เครื่องมือที่เหมาะตั้งแต่แรก มองว่า shell เหมาะกับสคริปต์เล็ก ๆ ราว 20 บรรทัดเท่านั้น ตัวภาษาเองคุณภาพยังไม่ดีพอสำหรับงานที่ใหญ่กว่านั้น
    • แนะนำ mise ที่บริษัทใช้อยู่เพื่อจัดการ development environment และตั้งค่าสภาพแวดล้อมได้ง่ายกว่า Docker กับ Nix มาก รองรับการติดตั้งแบบขนาน เลยรู้สึกว่าได้เปรียบกว่า Dockerfile ทั่วไปมาก
  • เป็นเทรนด์ที่เจ๋งมากจริง ๆ และรู้สึกว่ากำลังแพร่หลายขึ้นเรื่อย ๆ เจอครั้งแรกจากบล็อกของ simonw และไปดูรายละเอียดเพิ่มใน โพสต์บล็อกของ simonwillison เมื่อเดือนมีนาคมปีนี้ก็มี การถกเถียงบน Hacker News จากบทความบล็อกอีกชิ้นด้วย อยากให้เทรนด์นี้อยู่บนหน้าแรกนาน ๆ เพื่อให้คนรู้จักมากขึ้น

  • ลองใช้ uv กับโปรเจ็กต์เล็ก ๆ แล้วประสบการณ์ดีมาก การใช้ uv run กับ uv tool run (uvx) ทำให้ติดตั้งและรันสคริปต์ Python จาก GitHub บน VM ได้ง่ายสุด ๆ ไม่ต้อง git clone, ไม่ต้องสร้างหรือเข้า venv, และไม่ต้อง pip install ที่สำคัญคือ uv เร็วมากจนตอนแรกนึกว่ามีอะไรผิดพลาด ทั้งที่จริงแล้วเร็วกว่า pip 10 เท่า แค่ตัวเครื่องมือกับเอกสารยังดูไม่สมบูรณ์อยู่บ้าง แต่ด้วยความล้ำและความใช้งานได้จริงระดับนี้ก็ถือว่าใช้ได้สบาย

    • ประทับใจจริง ๆ ที่ uv ติดตั้ง dependency ได้เร็วกว่าที่ pyenv ใช้เวลาแสดง --help เสียอีก
  • ฝั่ง Rust ก็พัฒนาแนวคิด shell script แบบไฟล์เดียวคล้าย ๆ กันอยู่เหมือนกัน เดิมทีเคยเห็นแนวทางนี้ใน Rust เป็นที่แรก โดยรองรับการรันไฟล์เดียวพร้อมจัดการ dependency อยากให้แพตเทิร์นนี้เกิดขึ้นในภาษาอื่น ๆ มากขึ้น เพราะมีประโยชน์มากสำหรับการแชร์ผ่าน gist หรือเขียนเครื่องมือเล็ก ๆ แบบรวดเร็ว ดู เอกสาร cargo-script RFC ได้ด้วย

  • เวลาใช้ uv run --script แล้วฝัง metadata ไว้ในสคริปต์ จะรู้สึกว่าเปิด Python REPL จากสคริปต์โดยตรงเพื่อแก้และทดสอบไม่ค่อยสะดวกเท่าไร ตัวอย่างเช่นต้องทำแบบนี้

    $ uv run --python=3.13 --with-requirements <(uv export --script script.py) -- python
    >>> from script import X
    

    เลยหวังว่าจะมีวิธีที่กระชับกว่านี้ เช่นถ้าทำได้แบบนี้จะดีมาก

    $ uv run --with-script script.py python
    

    แต่ในทางปฏิบัติ ถ้ารันแบบด้านล่างก็เข้า Python และสภาพแวดล้อม venv ที่ตรงกับสคริปต์ได้ทันที

    $ "$(uv python find --script script.py)"
    >>> from script import X
    

    แค่ต้องรันสคริปต์สักครั้งก่อนเพื่อสร้าง environment

    • ถ้าต้องการฟังก์ชันเรียก REPL หลังเซ็ตอัปเสร็จ แนะนำดู ตัวอย่าง gist นี้ สามารถใส่แฟลกอย่าง --interactive ลงในสคริปต์ให้เป็นตัวเลือก CLI ได้ ปกติมักเขียน CLI เล็ก ๆ ด้วย Typer ในลักษณะนี้บ่อย ใน dev script ก็เคยใช้แฟลก --sql เพื่อเข้า DuckDB SQL REPL ด้วย
    • มีอีกวิธีง่าย ๆ แบบหนึ่ง
      cat ~/.local/bin/uve
      #!/bin/bash
      temp=$(mktemp)
      uv export --script $1 --no-hashes > $temp
      uv run --with-requirements $temp vim $1
      unlink $temp
      
  • ถ้าใช้ conda ก็สามารถทำ shell wrapper สำหรับสคริปต์ Python ที่ activate environment โดยตรงได้ เขียนประมาณนี้

    #!/usr/bin/env bash
    eval "$(conda shell.bash hook)"
    conda activate myenv
    python myscript
    

    แต่ก็เป็นแนวทางที่ไม่ได้แยกตัวเป็นอิสระเหมือนสไตล์ PEP 723

  • หลังจากเห็นเธรด HN เมื่อวานกับวันนี้ ก็เลยตัดสินใจลอง uv เป็นครั้งแรก และประทับใจมากกับความเร็วและการจัดการ dependency ที่ง่าย ถ้าเอกสารทางการดีขึ้นก็น่าจะยิ่งดี โดยเฉพาะถ้ามีคู่มือย้ายจาก workflow แบบ requirements.txt มาเป็น uv จะสะดวกมาก เรื่องการกำหนดเวอร์ชัน Python รายโปรเจ็กต์ก็ดูชวนสับสนอยู่เหมือนกัน เพราะมีทั้ง .python-version และ pyproject.toml ให้กำหนด

    • เคยเขียนอีบุ๊กสำรวจเครื่องมือสำหรับนักพัฒนา Python เลยเคยช่วยอธิบายส่วนที่เอกสารทางการยังขาดไว้บ้าง เช่น วิธีย้ายจาก requirements.txt และ วิธีเปลี่ยนเวอร์ชัน Python ของโปรเจ็กต์ uv ถ้ามีหัวข้ออื่นที่อยากให้ครอบคลุมเพิ่มเติมก็เสนอมาได้เสมอ
    • ฟิลด์ requires-version ใน pyproject.toml หมายถึงช่วงเวอร์ชันที่รับประกันว่าเข้ากันได้ ส่วน .python-version ใช้ระบุเวอร์ชันเฉพาะที่จะใช้พัฒนา ตอนสร้างด้วย uv init ใหม่ ๆ มันอาจดูเหมือนกัน แต่พอเวลาผ่านไป requires-version มักจะกลายเป็นเวอร์ชันขั้นต่ำที่รองรับ ซึ่งต่ำกว่า .python-version requires-version ยังเข้าไปอยู่ใน package metadata และมีผลต่อการแก้ dependency ของคนอื่นที่จะนำแพ็กเกจที่คุณปล่อยไปใช้ด้วย เช่น v1 ยังรองรับ Python เวอร์ชันเก่า แต่ v2 ไม่รองรับแล้ว เป็นต้น
    • ก็รู้สึกคล้ายกันในอีกมุม เพราะยึด workflow ของตัวเองแบบซิงก์ไฟล์เดียวกันไปทุกเครื่องผ่าน Dropbox แล้วใช้งานข้ามแพลตฟอร์ม บนแพลตฟอร์มที่เปลี่ยนไป npm หรือ dotnet อาจต้อง npm update หรือ dotnet restore แต่ venv ยังทำงานได้ไม่มีปัญหา ในขณะที่ uv เวลาสลับแพลตฟอร์มกลับรู้สึกว่ายุ่งยากกว่าและต้องล้างอะไรเองมากกว่า
    • pyproject.toml มีไว้เพื่ออธิบาย environment ที่ต้องใช้เวลาแชร์โค้ดให้ผู้พัฒนาหรือผู้ใช้ภายนอก โดยไม่ได้เกี่ยวกับ uv โดยตรง เวลาสร้างแพ็กเกจสำหรับ PyPI ก็ใช้ระบุว่าต้องการ environment แบบไหน และกำหนดช่วงเวอร์ชันเพื่อให้คนอื่นนำโค้ดไปใช้ซ้ำได้กว้างขึ้น ส่วน .python-version นั้น uv ใช้อ้างอิงเฉพาะตอนเซ็ตอัป development environment ของฉันเท่านั้น ถ้ามี environment ที่เตรียมไว้ล่วงหน้าอยู่แล้ว ก็ไม่จำเป็นต้องตั้งค่าใหม่ก็ได้ uv ยังไม่ใช่ official build backend แต่กำลังเตรียมฟีเจอร์นั้นอยู่ (issue #3957)
    • ยังไม่เคยลงลึกมากนัก แต่เดาว่าหน้าที่ของไฟล์ .python-version คงมีไว้เพื่อความเข้ากันได้กับเครื่องมืออื่นที่ไม่มี TOML parser
  • เคยมีประสบการณ์อยากทำเครื่องมือที่ให้สคริปต์ Python ติดตั้ง dependency เองได้อัตโนมัติ (ตั้งใจให้ทำงานคล้าย uvx แต่ขอแค่มี Python ก็ใช้งานได้) แต่ข้อเสียคือจำเป็นต้องใส่บรรทัดแปลก ๆ หลายบรรทัดไว้ต้นสคริปต์ ถ้าสนใจก็ปล่อยไว้บน PyPI ในชื่อ pysolate

    • มีโปรเจ็กต์ isolate ที่คล้ายกันแต่ไม่ค่อยแพร่หลายด้วย วิธีการต่างกันเล็กน้อย แต่ก็เป็นแนวทางที่น่าสนใจ
  • มีข้อความสไตล์ Grace Hopper ที่ได้แรงบันดาลใจจาก COBOL มองว่าทุกโปรแกรม Python ควรมีการกำหนด ENVIRONMENT division เพื่อระบุสภาพแวดล้อมที่ใช้คอมไพล์และรันอย่างชัดเจน รวมถึงข้อกำหนดด้านฮาร์ดแวร์และซอฟต์แวร์ และเชื่อว่าโครงสร้างแบบนี้จะมีผลสำคัญอย่างยิ่งต่อการทำให้โปรแกรมพกพาได้ดีขึ้นข้ามหลายระบบ