เขียนงูให้วัวกลัวรายสัปดาห์ ฉบับที่ 2

ข่าวประจำสัปดาห์ Dropbox complete migrate to Python 3 เวลานี้คงไม่มีใครไม่รู้จัก Dropbox นะครับ แต่อาจจะมีคนไม่รู้ว่า Dropbox เป็นหนึ่งในบริษัทที่ใช้ Python ใหญ่ที่สุดในโลก เฉพาะโค้ดของตัว Application Dropbox นี่ก็เกิน 1 ล้านบรรทัดแล้วครับ แต่ว่าถึงจะใช้ Python ใหญ่ที่สุดในโลกโค้ดของที่นั่นก็ยังเป็น Python 2 อยู่ครับ ซึ่งทาง Dropbox เองก็วางแผน Migrate มาตั้งแต่ปี 2015 แล้ว จนถึงวันนี้ ถ้าใครใช้ Application dropbox เวอร์ชั่นล่าสุด ตัวโค้ดที่รันอยู่ข้างล่างก็มีพื้นฐานจาก Python 3.5 เวอร์ชั่นพิเศษแล้วครับ ซึ่งทางบล็อกนี้อธิบายขั้นตอนการ Roll out ตัวโค้ดจาก Python 2.7 -> Python 3 และปัญหาที่เจอคร่าวๆ ครับ นอกจากนั้นแล้ว บล็อกนี้เป็นหนึ่งในซีรีย์บล็อกที่จะตามมาอีกหลายบล็อกจาก Dropbox เกี่ยวกับการ Migrate ไปใช้ Python 3 ก็คอยติดตามกันต่อไปได้ครับ How we rolled out one of the largest Python 3 migrations ever — Dropbox, Max Bélanger ...

September 27, 2018 · 5 min

เขียนงูให้วัวกลัวรายสัปดาห์ ฉบับที่ 1

ไอเดียนี้เริ่มจากอาทิตย์ที่แล้ว ที่รวบข่าวไว้ในโพสๆ เดียว แล้วก็เกิดไอเดียว่า ทำไมไม่ทำเป็น Newsletter เลยหละ มันเลยเป็นที่มาของโพสนี้และโพสต่อๆ ไปครับ โดย​ “เขียนงูให้วัวกลัว รายสัปดาห์” เราจะโฟกัสเฉพาะข่าวที่เกี่ยวข้องกับ Python Community, Core Language / 3rd Parties Release และอื่นๆ ที่มันเกี่ยวข้องกับ Python programming language ครับ Python Core Sprint 2018 Image credit: https://twitter.com/VictorStinner/status/1041219533439217665 ทุกๆ ปี Core Python developers จากทั่วทุกมุมโลกจะมารวมตัวกันโดยนัดหมาย 7 วันเพื่อคุยกันในหลายๆ เรื่อง ปีนี้เป็นครั้งที่ 3 ที่จัดขึ้นครับ ซึ่งผมก็ไม่รู้ทั้งหมดว่าเค้าคุยอะไรกันบ้าง แต่คุณ Mariatta Wijaya ซึ่งเป็นหนึ่งใน Core developer ได้สรุปไว้คร่าวๆ ครับ สนใจก็ตามไปอ่านได้ที่ลิ้งค์นี้เลย (ยังรอ Part two อยู่ T_T) Python Core Sprint 2018: Part One For the past week (September 9-14), I’ve been down in Bellevue, WA for my second Core Python sprint. The sprint is hosted by Microsoft, and funded by The PSF. Thanks Last year, I was only able to stay for the sprint for three days. This year I’m able to stay … — mariatta.ca, Mariatta ...

September 21, 2018 · 5 min

Share ประสบการณ์ Upgrade Python 3.7

ถ้าจะมีงานหนึ่งที่ผมทำแล้วรู้สึกสนุกและท้าทายทุกครั้งที่อยู่ที่ Pronto Tools ก็คือการอัพเกรดเวอร์ชั่น Python นี่แหละครับ ตอนผมเข้ามาทำงานใหม่ๆ ทีมใช้ Python 3.5 อยู่ปีที่แล้วเลยอัพเกรดเป็น 3.6 และในปีนี้เนื่องในโอกาส Python 3.7 ออก เราก็รอแปปนึงจนคิดว่าอะไรๆ พร้อมแล้ว ถึงจะอัพเกรด ทำไมถึงต้องอัพเกรด เพราะเราอยากใช้ของใหม่ๆ ครับ อันนี้เหตุผลสั้นๆ เลย เราอยากใช้ breakpoint() ตัวใหม่ เราอยากใช้ dataclasses เราอยากใช้ from __future__ import annotations และอื่นๆ อีกมากมาย นี่ยังไม่รวมถึง Library ต่างๆ ที่เกี่ยวข้องที่บาง Library ทำมาเพื่อ Python 3.7+ แล้ว ถึงแม้ว่า Python 3.6 กว่าจะ end of life ก็ตั้งปี 2021 แต่รีบๆ อัพเกรดไว้ก็ไม่เสียหายครับ ข้อดีอีกอย่างของการอัพเกรดในช่วงนี้คือ หา Issues ง่ายครับหลายๆ Library ที่เราพึ่งพาอยู่ในโปรเจ็คเราก็ยังมีอีกหลายคนที่ต้องการอัพเกรดเหมือนกัน แต่ถ้าหาไม่เจอ นี่ก็เป็นโอกาสอันดีครับที่จะได้ไป Contribute ให้ Library หลายๆ ตัวให้รองรับ Python 3.7 ในตัว ...

September 8, 2018 · 5 min

สร้าง Load Test ง่ายๆ ด้วย Locust

#pythontricks วันนี้ครับ พอดีวันนี้มีปัญหากับ API แล้วต้องทำ Load test แบบง่ายๆ เร็วๆ เลยไปเจอ locustio มาครับ และมันง่ายมากเลย Locust เป็น Load testing tool ตัวนึงครับ ผมไม่เคยใช้ตัวอื่นแต่พอมาใช้ตัวนี้ วันนี้ เช้านี้ บอกได้เลยว่ามันใช้ง่ายมากครับ เพียงแค่เราสร้าง TaskSet ขึ้นมา โดย TaskSet เนี่ยจะเป็นคล้ายๆ Test Case ว่าเราจะทำอะไรกับ Server บ้าง ในเคสนี้ก็คือยิง HTTP Request ครับ ลักษณะการเขียนจะคล้ายๆ กับพวกเทสของ Django หรือ DRF เลยคือเป็น self.client.<method> พอเราเขียน TaskSet เสร็จแล้วเราก็ต้องสร้างอีก Class นึงครับเป็น Locust class ซึ่ง Class นี้จะเป็นตัวแทนของ User ที่ใช้ TaskSet อีกทีนึง ซึ่งเราสามารถกำหนด min_wait และ max_wait ได้ซึ่งจะเป็นค่าที่ตัว Locust ใช้สุ่มในการ Generate Task ขึ้นมาครับ พอเราเขียนเสร็จแล้วหน้าตาของ locustfile.py ก็จะประมาณนี้ ...

August 29, 2018 · 1 min

Patch ยังไงให้อ่านรู้เรื่อง

สิ่งหนึ่งที่เราจะเจอหลังจากเขียน Unit Test มาได้ซักพักคือ มันจะมีบางอย่างที่เราควบคุมมันไม่ได้ครับ บางอย่างนั้นอาจจะเป็นไปได้ตั้งแต่ ค่าสุ่ม, เวลา, การอ่านเขียนไฟล์,​ การแก้ไข Database อะไรอย่างนี้เป็นต้น พอเรามาเจออะไรพวกนี้ มันจะเกิดคำถามขึ้นมาทันทีว่า แล้วเราจะเทสมันยังไง ถ้ามันเปลี่ยนตลอดเวลา คำตอบของคำถามนั้นก็คือ เราต้อง Mock มันครับ ซึ่ง Python มี standard library ไว้จัดการเรื่องนี้ครับคือ unittest.mock.patch Patch นั้นมีหลายท่า ก่อนหน้านี้ผมเคยเล่าให้ฟังบางส่วนแล้วว่าเราจะจัดการกับการ Patch หลายๆ module ยังไง ซึ่งใช้ ExitStack() มาช่วยในการจัดการ context สนใจไปอ่านต่อได้ที่นี่ครับ Python - ExitStack แบบสั้นๆ วันที่ 7 ของ #PythonTricksEveryday วันนี้ขอเสนอ ExitStack() ครับ มาช้าหน่อยนะครับวันนี้ มัวแต่ตื่นเต้น 1,000 likes โอเค เข้าเรื่องดีกว่า ก่อนจะไปรู้จัก ExitStack เราต้องรู้จักสิ่งที่เรียกว่า context manager ก่อนครับ context manager — Yothinix, Yothin Muangsommuk แต่จริงๆ เราสามารถใช้ patch ได้ถึง 3 แบบเลย แล้วแต่สถานการณ์ครับ ...

August 18, 2018 · 2 min

Python - ExitStack แบบสั้นๆ

วันที่ 7 ของ #PythonTricksEveryday วันนี้ขอเสนอ ExitStack() ครับ มาช้าหน่อยนะครับวันนี้ มัวแต่ตื่นเต้น 1,000 likes โอเค เข้าเรื่องดีกว่า ก่อนจะไปรู้จัก ExitStack เราต้องรู้จักสิ่งที่เรียกว่า context manager ก่อนครับ context manager เนี่ยจะเป็นตัวจำกัดการเข้าถึงและปล่อย Resource หนึ่งๆ ซึ่ง keyword ที่เราคุ้นเคยที่สุดน่าจะเป็น with ใช่มั้ยครับ ตัว Resource ที่เราพูดถึงกันนี้ง่ายที่สุดก็น่าจะเป็นไฟล์ หรือการต่อ database อะไรเทือกนี้ใช่มั้ยครับ ทีนี้เวลาเราจะเปิดไฟล์หลายๆ ไฟล์ สิ่งที่เกิดขึ้นคือมันก็จะเกิดอาการ with ซ้อน with ไปเรื่อยๆ จนกระทั่ง Python 3.3 ได้เพิ่ม ExitStack() เข้าไปใน contextlib ครับโดย ExitStack() ตัวนี้จะช่วยจัดการเกี่ยวกับ context manager ได้ดียิ่งขึ้นกว่า nested with ที่เคยใช้กันมา แต่ในเคสที่ผมกำลังพูดถึงนี่คือการเขียน Unit Test ครับและเป็นเทสที่มี Mock เข้ามาเกี่ยวข้องด้วย และที่พิเศษกว่านั้นคือต้อง Mock เยอะๆ ด้วยครับ จะเห็นว่า example_function เรามีของที่มี side effect แล้วเราต้อง Mock() อยู่สองอย่างใช่มั้ยครับคือ randint และ datetime.now() แต่ก่อนตอนผมเขียน Unit Test ที่ต้อง Mock อะไรแบบนี้ ผมจะไปเหมือน test case แรกเลยครับ คือใช้เป็น decorator patch() แปะอยู่บนหัวของ test case วิธีนี้ใช้ง่ายครับ แต่จะเริ่มมีปัญหาตามมาเมื่อเริ่ม Mock() มากกว่าหนึ่งตัว ปัญหาแรกคือ มือใหม่จะสับสนมากว่าที่ patch เรียงๆ กันเนี่ย argument ของ test case มันคือตัวไหน สำหรับคนที่ยังไม่รู้นะครับ argument ของ decorator จะเรียงจากในไปนอกครับ ...

July 31, 2018 · 1 min

Why I love Python so much

ในโอกาสที่เพจ เขียนงูให้วัวกลัว ครบ 1000 likes ผมเลยคิดได้ว่า เออ อยู่ดีๆ ผมก็มาทำเพจเอามันส์ อยากเขียนอะไรก็เขียน แล้วก็มาสงสัยกับตัวเองบางครั้งว่า ทำไมเราถึงมีความรู้สึกอยากจะทำเพจนี้มากขนาดนี้ ผมเลยมองย้อนกลับมาหาตัวเองว่า ทำไม เราถึงชอบภาษานี้มากขนาดนี้ มันมีเหตุผลอะไร ผมจะพาไปไล่ดูครับว่าทำไมผมถึงรักภาษานี้มากและอาจจะเป็นเหตุผลให้คุณรักภาษานี้เหมือนกันก็ได้ Beautiful is better than ugly 💄 hello world แบบ Python นะครับ ส่วนแรกที่ผมชอบเกี่ยวกับภาษานี้คือ Semantic มันครับ เรื่องนี้ต้องย้อนไปถึง Design Philosophy ของตัวภาษาเลยว่ามันถูกออกแบบมาให้เป็นภาษาที่อ่านได้ง่ายมากๆ โดยใช้ keyword ภาษาอังกฤษ แทนที่จะใช้เครื่องหมายต่างๆ รวมไปถึงใช้ Indentation แทนที่จะใช้ curry bracket ในการกำหนด scope เป็นต้น ด้วยตัวภาษาเองยังเป็นภาษา Multi-paradigm ทำให้รองรับรูปแบบการเขียนโปรแกรมหลายรูปแบบมากตั้งแต่ Imperative, Object Oriented, Functional, Procedural และ Reflective ทำให้เราไม่ถูกจำกัดแนวคิดในการแก้ปัญหาต่างๆ ด้วยภาษานี้ถึงแม้มันจะขัดกับ Zen of Python ข้อ There should be one — and preferably only one — obvious way to do it. ก็เถอะ ...

July 31, 2018 · 2 min

Dedent your multiline string

วันที่ 2 ของ #PythonTricksEveryday นะครับ ไหนๆ ก็เป็นวันสุดท้ายของการทำงานก่อนจะถึงวันหยุดยาว ขอแนะนำด้วย Tricks เล็กๆ ที่จะช่วยให้การทำงานกับ Multiline String เราดีขึ้นครับ สมมติว่าเรามี String ยาวๆ ที่ต้องมี Indent สวยๆ เช่น Email หรือ Code snippet อย่างในภาพ แล้วเราต้องการนำมันไปใช้งานเช่นส่งอีเมล์หรือ Print report อะไรแบบนี้ จะเห็นว่าพอ print ค่าออกมาแล้ว string ที่เราเก็บไว้มี space ติดมาด้วย สิ่งที่เกิดขึ้นคือ Multiline String ของ Python จะนับ tab ที่เราเว้นไว้ทางซ้ายด้วย เหมือนในฟังก์ชั่น process_something() ซึ่งถ้าเราไม่อยากให้มันเยื้องแล้ว Print ออกมาสวยๆ เราก็ต้องทิ้งเยื้องไป เหมือนในฟังก์ชั่น process_something_without_padding() ซึ่งพอเราทำแบบนี้ ผมว่าทุกคนน่าจะรู้สึกทันทีว่า เออมันเวิร์คนะแต่ Indent มั่วไปหมดเลย พ้น definition ของ function ไปอีก ยิ่งถ้าเป็น Method ที่อยู่ใน class ยิ่งไม่อยากจะคิดเลย ...

July 26, 2018 · 1 min

The Power of Any / All

วันที่ 1 ของ #PythonTricksEveryday นะครับ วันนี้เปิดด้วยหนึ่งในเทคนิคที่ พอรู้แล้วก็ใช้ได้ตลอดเลย มันคือ built-in function ที่ชื่อว่า all() และ any() ครับ ไปดูสถานการณ์เลยดีกว่า สถานการณ์ที่เรามักจะเจอกันบ่อยๆ คือ เราต้องเขียน if ที่มี condition เยอะมากๆ อย่างในตัวอย่างนี้ก็ 5 conditions ซึ่ง บางทีรูปแบบที่มันอยู่อาจจะอยู่ยากกว่านี้ก็ได้ เช่น เป็น if แยกกันหลายๆ อันหรือ if ซ้อนใน if ให้เราลองพยายาม normalize ให้มันเหลือ if เดียวแล้วให้ความสัมพันธ์ของมันเหลือแค่ and / or พอเรา normalize ความสัมพันธ์ของแต่ละ condition จนเหมือนภาพข้างบนแล้ว สิ่งที่เกิดขึ้นก็คือ Linter ด่าครับ ยาวเกิน 80 บรรทัดอะไรก็ว่าไป ซึ่งเราก็จะต้องตบมันเข้ามาให้ไม่เกิน 80 บรรทัด โค้ดข้างล่างนี้ผมใช้ Black ช่วย Format ให้นะครับหน้าตาก็จะประมาณนี้ ...

July 25, 2018 · 2 min

Mock requests แบบสวยๆ ด้วย responses

สิ่งหนึ่งที่เราเจอไม่ว่าจะช้าหรือเร็วคือ เมื่อเขียน Python ไปซักพักเราต้องยุ่งกับการยิง HTTP request ไปหา service ข้างนอก ซึ่ง Library ที่นิยมที่สุดในการทำสิ่งนี้ใน Python ก็คงหนีไม่พ้น requests นะครับ สมมติเรามีฟังก์ชั่น process_something ที่ทำหน้าที่ยิง requests ไปหา service ข้างนอกแล้วคืนของออกมาเป็น dictionary หน้าตาประมาณนี้ process_something.py ถ้าเขียนแบบสมัยก่อน เราก็จะต้อง patch ตัว requests.get แล้วสร้าง Mock() object มารับ return_value หน้าตาประมาณนี้ ซึ่งพอทำแบบนี้บ่อยๆ เราก็เริ่มเห็น Pattern ซ้ำๆ ครับว่าต้อง Mock status_code นะ json() call นะหรือแม้กระทั่ง content type กับ headers ในบางเคส วิวัฒนาการถัดมาของการ mock requests คือ พอเราเห็น pattern ซ้ำๆ เราก็จับมันมาทำ utils function ครับ ซึ่งหน้าตามันก็จะออกมาประมาณนี้ ...

July 24, 2018 · 2 min