สวัสดีครับบทความนี้เขียนเพื่ออธิบายถึง virtual environment ซึ่งเป็นหนึ่งในหัวข้อที่คนที่เขียน Python อาจจะข้ามไปเนื่องจากบางที IDE อาจจะจัดการส่วนนี้ให้หรือบางสายงานอาจไม่จำเป็นต้องใช้ในส่วนนี้
หรือท่านไหนอยากอ่านเพลินๆ ก็ตามสะดวกครับ
หัวข้อในบทความนี้
Virtual environment คือสภาพแวดล้อมที่จะแยกแต่ละโปรเจคออกจากกันเช่น คุณอาจอยากเขียน Django2 ในโปรเจคหนึ่ง แต่ในอีกโปรเจคหนึ่งอาจจะใช้ Django3 พอใช้ virtual environment ปัญหานี้ก็จะหมดไป (ใน IDE แบบ Pycharm จะสร้าง virtual environment ให้เองทุกครั้งที่สร้างโปรเจคใหม่) และเพื่อให้เวลาที่เราแชร์ environment ให้คนอื่น จะได้ระบุแค่สิ่งที่ต้องใช้ไม่พ่วง libraryที่ไม่ต้องการไปด้วย
หากใครที่ใช้ python ก่อน 3.5 จะต้องลง
virtualenv แต่ในเวอร์ชั่น 3.5 ขึ้นไปนั้นจะมี venv(เป็นส่วนหนึ่งแยกมาจาก virtualenv)
มาให้อยู่แล้วไม่ต้องลงอะไรเพิ่ม
python3 -m venv <ชื่อ enviroment>
เมื่อเราสร้าง environment แล้วเราต้องทำการ activate
ก่อนด้วยคำสั่ง
Source <env>/bin/activate # สำหรับ mac หรือ linux
<env>/Scripts/activate #สำหรับฝั่ง windows
ใน windows เราสามารถเรียกไฟล์ activate ได้เลยแต่ใน Mac/Linux จะต้องใช้คำสั่ง source ก่อน
จากรูปจะสังเกตได้ว่าเมื่อเราเปิดใช้งาน path ของคำสั่งต่างๆจะเปลี่ยนไป
สำหรับใครที่ใช้ Windows และเปิดใน Powershell จะมีปัญหาเรื่อง Script Policy อยู่สามารถรันคำสั่งดังต่อไปนี้เพื่อแก้ไขได้ แต่จำต้องรัน Powershell ด้วยสิทธิ Administrator
Set-ExecutionPolicy Allsigned CurrentUser
และเลือก Always run หากใครไม่ซีเรียสเรื่อง policy เครื่องก็รันด้านล่างเลยก็ได้
Set-ExecutionPolicy Unrestricted -Force
หากใครไม่สามารถใช้สิทธิดังกล่าวก็อาจจะใช้ CMD แทนได้ รายละเอียด policy อ่านได้ที่ ลิ้งค์นี้
จะสังเกตได้ว่าเมื่อเรา activate เรียบร้อยแล้วจะมีชื่อ environment
นำหน้าคำสั่งของเรา ในทีนี้ก็คือ (env) เมื่อเราต้องการจะปิดเราก็สามารถทำได้ด้วยคำสั่ง
deactivate
เพียงเท่านี้ก็เสร็จแล้ว
บางคนอาจไม่เคยสร้าง virtual enviroment ขึ้นมาเอง แต่ส่วนใหญ่น่าจะเคยเห็นคำสั่งอย่าง
pip install
กันมาบ้างใช่ไหมล่ะครับ
pip คือ package installer/manager สำหรับ python เพื่อลง library ต่างๆจาก PYPI(Python Package Index) ถ้ามองง่ายๆก็คือตัวนึงไว้ลง อีกตัวเป็น repo หรือที่เก็บ library ต่างๆออนไลน์ไว้ให้เราดาวโหลดง่ายๆ อย่างตัวที่ดังๆไม่ว่าจะเป็น numpy pandas tensorflow matplotlib อะไรพวกนี้
ซึ่งการลงก็ทำได้ง่ายๆ เรา activate environment ขึ้นมาก่อน เช่นผมอยากลง numpy ก็ใช้
pip install numpy
ทาง pip ก็จะไปโหลดมาจาก PYPI ลงมาให้(และแน่นอนว่าต้องใช้อินเตอเน็ตนะครับ )
หากเราต้องการลงเวอร์ชั่นที่เจาะจงก็ใช้คำสั่ง pip install numpy==<version> ได้แล้วก็แทนเวอร์ชั่นลงไปเช่น
pip install numpy==3
หรืออาจจะไม่ต้องระบุเป๊ะๆ
อาจใช้เป้นเครื่องหมายก็ได้เช่น
pip install 'numpy>=1.1,<2'
หากเราต้องการลบก็ใช้คำสั่ง
pip uninstall numpy
และในกรณีที่เราอยากรู้ว่าใน virtual environment เรานั้นลงอะไรไว้บ้างก็สามารถรันคำสั่ง pip freeze เพื่อดูได้
pip install numpy
เคยไหมครับเวลาก็อบ code เราไปให้เพื่อนเราใช้แต่ว่าเขารัน code ไม่ได้? ปัญหานี้อาจจะเกิดจาก version อะไรต่างๆที่ไม่ตรงกันหรือ environment ของเพื่อนเราอาจจะยังไม่มี package ที่ต้องใช้
ถ้าใครเคยลองก็อบปี้โฟลเดอร์ env ไปตรงๆเลย ส่วนใหญ่ก็น่าจะพบว่าใช้ไม่ได้เพราะ settings, path ต่างๆมันไม่เหมือนกัน วิธีแก้ทำคือการสร้างไฟล์ requirements.txt ขึ้นมา ผ่านคำสั่ง pip freeze แล้วให้เพื่อนลง package ต่างๆที่ต้องใช้ผ่านไฟล์นั้น ซึ่งหากใครไม่ได้สร้าง virtual environment ไว้เนี่ยเวลา pip freeze ออกมาทีมันก็จะยาวเหยียดตามงานทุกอย่างที่เราเคยเขียน
pip freeze >> requirements.txt
และคนที่จะลงก็เอาไฟล์ requirements.txt มาด้วยและรันคำสั่ง
pip install -r requirements.txt
ทาง pip ก็จะลง package ตามรายชื่อที่อยู่ใน requirements.txt
จริงๆในหัวข้อนี้ไม่ค่อยมีความจำเป็นเท่าไหร่ จากในตอนแรกที่เรามีปัญหาคือเราจะเขียน django2,3 เราก็สร้าง environment ขึ้นมาสองชุดแก้ปัญหาเรียบร้อยดีใช่ไหมครับ แต่ทีนี้มันมีปัญหาต่อมาคือว่า ถ้าเกิดว่าเราใช้ package 2 ตัว(สมมุติเป็น flask, django) แล้วมันใช้ package ตัวหนึ่งร่วมกันแต่คนละเวอร์ชั่นกัน ผมตั้งชื่อให้ว่า package A แล้วกัน
Django2 ใช้ A version > 1.0ส่วน Flask ใช้ A > 1.0, A < 2.0
จริงๆเราก็แค่ 1.x ใช่มะแต่ในก่อน pip 20.3 (อัพเดตเมื่อเดือน 11 ปี 2020 )เจ้า pip มันจะเลือก package ตัวแรกเช่นถ้า Django โผล่มาก่อนมันก็จะเลือก package A > 1.0 เพราะมันไม่มี true dependency resolver ลองอ่านเพิ่มเติมได้ที่นี่ และ ที่นี่
แต่ถ้าหากสอง library มันดันใช้ package ร่วมกันที่เวอร์ชั่นไม่ตรงกันอีกล่ะ
เช่น A > 1.0 , A < 1.0
สิ่งที่เกิดขึ้นเราจะเรียกมันว่าปัญหา dependency hell นั่นเอง :(
อ้างอิงจาก blog ของทาง anaconda ก็ประมาณว่า pip มันเป็น package manager ไว้โหลดอะไรต่างๆจาก PYPI ใช่ไหม แต่ Conda มันมีระบบ virtual environment มาให้ด้วย (pip ต้องไปใช้แยกคู่กับพวก venv pipenv) และด้วยความที่สมัยก่อน pip มันดันไม่มี dependency resolver มาให้ทำให้การลงอะไรต่างๆบางทีมันก็ลงไม่ได้ conda ก็เลยเป็นอีกทางเลือกนั่นเอง ส่วน miniconda นั้นเนื่องจาก conda มันทำการลง package อะไรต่างๆมาให้พร้อมใช้งานซึ่งมันหนัก ตัว miniconda เลยตัดส่วน package หลายๆตัวออกไปแต่สามารถลงเองเพิ่มเติมได้
ปล.ผู้เขียนไม่ได้ใช้ conda สักพักใหญ่ๆแล้ว ในหัวข้อนี้หากมีข้อผิดพลาดขออภัย
หลายๆคนอาจจะเคยเห็นไฟล์ pipfile หรือ pipfile.lock ใน repository ของคนอื่นนั่นคือเพราะเขาใช้ pipenv นั่นเอง ข้อดีคือมันสามารถระบุแยกเวอร์ชั่น dev กับ production ได้ และเริ่มต้นใช้งานได้โคตรง่าย
pipfile ของ pipenv ที่ใช้แทน requirements.txt
การ install
เราสามารถลงได้ผ่าน pip โดยใช้คำสั่ง
python3 -m pip install pipenv
python3 -m pip install pipenv
ใน MacOS/Linux อาจจะลงผ่าน brew หรือ apt-get ก็ได้
brew install pipenv
sudo apt install pipenv
เมื่อเราได้แล้วเราลองปิดและเปิด terminal ใหม่ก่อนและลองพิม pipenv ก็จะมีตัวอย่างคำสั่งต่างๆขึ้นมาเป็นอันว่าลงเสร็จสมบูรณ์ (ใคร pip ไมได้อาจใช้ py -m pip install pipenv)
ตามขั้นตอนปกติหากเราใช้ venv คู่กับ pip เราจะต้องสร้าง environment และ activate มันซึ่ง pipfile จะรวมในคำสั่งเดียวนั่นคือ
pipenv shell
เมื่อเรารันทาง pip จะสร้าง virtual environment และ activate พร้อมกับสร้างไฟล์ขึ้นมานั่นคือ pipfile การทำงานของมันจะต่างจาก venv ตรงที่มันจะสร้าง shell ใหม่ขึ้นมา แต่ถ้าเป็นใน windows มันจะไม่ขึ้น (env) นำหน้าให้
ต่อมาเมื่อต้องการลง package อะไรปกติเราจะใช้ pip install แต่นี่เราจะใช้
pipenv install <package>
เหมือนกันมากๆและเมื่อเราทำการลง package ใดๆก็ตามมันจะเพิ่มไปยัง pipfile ให้อัตโนมัติ (ไม่ต้องมานั่งพิม pip freeze >> requirements.txt) นอกเหนือจากนี้เรายังสามารถระบุได้ด้วยเช่นผมอาจใช้ pytest แค่ใน dev แต่ใน production ไม่ใช้ผมก็ใส่ตามด้านล่าง pipenv มันก็จะไม่เอาลงใน pipfile.lock ให้
pipenv install pytest --dev
การระบุเวอร์ชั่นแบบเจาะจงก็ยังสามารถทำได้เหมือนเดิมเลยเช่น
pipenv install django==3
หรือหากเราต้องการลง package จาก requirements.txt ก็สามารถใช้
pipenv install -r requirements.txt
pipenv lock -r >> requirements.txt
ทดสอบรัน Django
การดู package และ dependency ที่ปกติเราจะใช้ pip freeze นั้นก็เปลี่ยนมาเป็น
pipenv lock -r
pipenv graph # จะมีการบอก sub dependency ด้วย
การออกจาก virtual environment นั้นเดิมทีเราจะใช้ deactivate แต่ในนี้เราจะใช้
exit
Tl;dr
สรุปคำสั่ง pipenv
สรุปจะใช้ pipenv ทำไรบ้าง
คลิปวิดีโอ (YouTube) แนะนำสำหรับ Python virtual environment
กิจกรรมที่กำลังจะมาถึง
ไม่พลาดกิจกรรมเด็ด ๆ ที่น่าสนใจ
Event นี้จะเริ่มขึ้นใน April 25, 2023
รายละเอียดเพิ่มเติม/สมัครเข้าร่วมคอร์สเรียนไพธอนออนไลน์ที่เราได้รวบรวมและได้ย่อยจากประสบการณ์จริงและเพื่อย่นระยะเวลาในการเรียนรู้ ลองผิด ลองถูกด้วยตัวเองมาให้แล้ว เพราะเวลามีค่าเป็นอย่างยิ่ง พร้อมด้วยการซัพพอร์ตอย่างดี