Khởi đầu dự án Python như thế nào để thuận tiện phát triển lên

Thỉnh thoảng có mối duyên ghé mắt qua các dự án Python, mình thấy cách sắp đặt vẫn còn chuệch choạc, không có lợi lắm cho việc phát triển tiếp diễn. Sau đây mình chia sẻ một số cách thức, công cụ, thư viện mà bạn nên chuẩn bị từ đầu, để công việc sau đó trở nên thoải mái hơn. Cách sắp đặt này có thể coi là chuẩn trong những năm 2020 này (nhưng có thể trở thành lạc hậu sau 5 năm nữa).

1. Quản lý các gói phụ thuộc

Gói phụ thuộc (dependency) là các thư viện / công cụ bên ngoài mà dự án của bạn cần. Các gói này phải được cài trước khi phần mềm của bạn có thể chạy. Ví dụ bạn làm về khoa học dữ liệu thì sẽ cần NumPy, làm web thì sẽ cần Django v.v... Việc một dự án phụ thuộc vào hàng chục gói thư viện khác là chuyện bình thường. Thông thường các gói này sẽ được liệt kê trong file requirements.txt để khi sao chép dự án sang máy khác thì biết cần cài cái gì. Tuy nhiên, file requirements.txt chỉ là hình thức tối thiểu để quản lý gói phụ thuộc. Nó không đủ để hỗ trợ tình huống phức tạp hơn. Ví dụ dự án của bạn sử dụng thư viện A phiên bản v1 và B phiên bản v2. Sau vài tháng nhu cầu nảy sinh, bạn cần thêm tính năng mới, và để làm tính năng mới, bạn cần đến thư viện C. Tuy nhiên thư viện C này cũng lại phụ thuộc thư viện A, và thư viện C đang có nhiều phiên bản, v1 đến v5, mỗi phiên bản của C sẽ thương thích với một phiên bản A khác nhau. Nếu bạn nhắm mắt chọn phiên bản mới nhất của C thì nó sẽ yêu cầu A v3. Bạn không thể mù quáng nâng cấp A lên v3 vì có thể phần mềm của bạn không tương thích và đứt gãy. Nhưng trong 5 phiên bản của C mà thử từng cái một thì rất cực. Đó là lúc bạn cần một thứ nâng cao hơn file requirements.txt.

...

API mở cung cấp dữ liệu công cộng Việt Nam

Dạo này tình hình dịch bệnh nghiêm trọng, phải ở nhà cả ngày nên mình tranh thủ làm một bộ API HTTP giúp truy cập dữ liệu mở, công cộng của Việt Nam.

Sản phẩm đầu tiên là API cung cấp dữ liệu tỉnh thành Việt Nam tại provinces.open-api.vn, ra mắt vào tháng trước:

Province API

API này dựa trên một thư viện Python, VietnamProvinces, mà mình đã xây dựng hồi còn làm việc tại SunshineTech.

...

Viết hàm thêm cho PostgreSQL: Chú voi bay

Vừa rồi tôi đã viết bài Dùng Python viết hàm xử lý dữ liệu dưới tầng database cho PostgreSQL. Sau khi chơi với Python một chút, tôi tự hỏi, có thể tăng tốc độ thực thi thêm nữa không. Thế nên hôm nay tôi nghịch thêm vài cách khác nhau, để gắn thêm tên lửa vào đít chú voi PostgreSQL.

Dumbo Picture credit: Walt Disney

Bây giờ tôi sẽ chuyển đổi code kia sang Cython và Rust.

...

Chuyển đổi Unicode dựng sẵn & tổ hợp với Python

Dạo này các ứng dụng với dữ liệu tiếng Việt đang ngày một nhiều, trong đó vấn đề sai khác giữa Unicode dựng sãn và tổ hợp, tuy nhỏ, nhưng cũng gây mất chút kha khá thời gian debug cho những người mới vào nghề. Mình chia sẻ xíu kinh nghiệm này, để việc phát triển ứng dụng tiếng Việt trở nên trơn tru hơn, và cũng để "khoe hàng" về hệ sinh thái giàu mạnh của Python.

Tưởng tượng một tình huống sau. Ứng dụng của bạn cho người dùng nhập vào một chuỗi tiếng Việt, khi nhận được chuỗi, phần mềm sẽ dò trong cơ sở dữ liệu để chọn ra bản ghi nào ăn khớp với chuỗi đó. Cơ sở dữ liệu này được một người khác nhập liệu. Bạn đã chắc chắn rằng chuỗi đó có tồn tại trong cơ sở dữ liệu, nhưng không hiểu sao phần mềm so sánh, dò tìm không ra. Hóa ra là người nhập liệu, khi gõ chuỗi vào thì dùng Unicode tổ hợp (decomposed), trong khi người dùng lúc nhập chuỗi tìm kiếm vào thì dùng Unicode dựng sẵn (composed). Dưới dạng chuỗi byte thì hai chuỗi này không giống nhau, nên bằng biện pháp so sánh chuỗi unicode thông thường, phần mềm sẽ không nhận ra.

Lấy ví dụ một chuỗi sau, Tiếng Việt bão táp, nếu là Unicode dựng sãn, khi thể hiện dưới dạng chuỗi byte, dàn theo bảng mã UTF-8, thì là chuỗi byte này:

...

Áp dụng quy trình hiện đại khi làm phần mềm cho hệ thống nhúng

Đi qua đi lại một vài đơn vị làm phần mềm nhúng, IoT Việt Nam, mình thấy không hài lòng lắm về cách làm việc hơi cũ. Mình thấy nhiều bạn làm điện tử có thể lập trình được, những vẫn còn một khoảng trống dài về phương pháp làm việc giữa những người này và những người thuần về phần mềm. Thế nên mình viết bài này, hi vọng kéo những người làm phần mềm nhúng tiến lên vài bước cho gần với chuẩn.

Lưu ý: Những cách làm sau đây, ban đầu sẽ gây thiệt thòi vì vẽ ra quá nhiều chuyện để làm, nhưng về lâu dài thì có lợi cho việc tiếp tục phát triển sản phẩm.

1. Chia nhỏ phần mềm thành những gói gần như độc lập

Lấy ví dụ về một hoạt động kiểm nghiệm ý tưởng thiết kế phần mềm tại AgriConnect.


CoBang, phần mềm quét mã QR cho Linux

Năm 2020 quả là một năm với nhiều biến động lớn, quy mô rung chuyển toàn cầu, tiêu điểm là dịch cúm CoVid-19 khiến nhiều cường quốc mất mặt và một nước "ít quan trọng" như Việt Nam trở thành điểm sáng. Hòa chung xu thế đó mình cũng tung ra một phần mềm "Made in Viet Nam" nhưng hướng đến người dùng quốc tế. Chém thế thôi chứ nó thật ra xuất phát từ nhu cầu cá nhân.

CoBang

CoBang là phần mềm quét mã QR dành cho desktop Linux. Mã QR đang ngày càng phổ biến, nó là phương tiện để trao đổi thông tin khó viết và khó nhớ. Một trong những hoàn cảnh mình bị buộc phải đụng đến mã QR là khi mình cần kết nối vào một mạng wifi nhưng không biết password. Thông tin wifi đó thì có lưu trong điện thoại nhưng điện thoại không cho xem password (một quan điểm kì cục của những người thiết kế HĐH điện thoại ban đầu). May thay hồi đó mình dùng điện thoại Xiaomi và nó nó chức năng chia sẻ thông tin wifi qua mã QR. Trong khi những phần mềm quét mã QR có ra rả trên Android thì trên Linux lại rất hiếm. Lí do của sự hiếm này là khi nói đến "quét mã QR", người ta chỉ hình dung đến việc cầm điện thoại lên soi thôi. Hồi đó trên laptop mình dùng QtQR nhưng khá cùi và có bug. Điều đó làm nảy sinh nhu cầu bức thiết là phải tạo một phần mềm mới. Dù nhu cầu là có nhưng vì có nhiều công việc gấp hơn nên mình đành trì hoãn đến năm nay mới bắt tay vào làm, nhân dịp muốn tìm một luồng gió mới thay cho công việc làm web hàng ngày.

Do cũng khá am hiểu những lớp công nghệ bên dưới desktop Linux nên mình dễ dàng hình dung được việc cần dùng những thư viện, công nghệ gì bên dưới và liên kết chúng ra sao. Thành tố quan trọng nhất là GStreamer, một thư viện/framework xuất sắc của thế giới Linux. Nó giúp hiện thực hóa ý tưởng của mình về cách luồng media vận hành ra sao: Sau khi lấy nguồn video liên tục từ webcam thì dòng video sẽ được chia làm 2 nhánh, một nhánh cho hiển thị lên cửa sổ giao diện, nhánh kia thì cho tách ra từng frame, lấy ảnh, và cho vào thư viện ZBar để soi tìm mã QR. Về giao diện đồ họa thì mình đi ngược với hot trend "cross-platform" để gắn bó với GTK, một thư viện native trên Linux.

...

Lại tản mạn về vai trò của Linux

Nghe đồn giới IoT muốn ứng dụng Bluetooth LE nhưng gặp khó.

Quay đi quay lại thì mình thấy thư viện về Bluetooth có độ hoàn thiện nhất là BlueZ. Khó ở đây là thư viện này được tạo ra với mục đích dành cho viết ứng dụng Linux, vì nó dùng event loop của GLib ở trỏng. GLib là một trong những thành phần lõi của bộ GTK, bộ toolkit dành cho lập trình giao diện đồ họa của Linux. Đã thế nó còn dùng D-Bus nữa chứ. D-Bus là một đường giao tiếp chung, cho phép các ứng dụng desktop giao tiếp với nhau. Sau đây là ví dụ về ứng dụng của D-Bus: Vào thời mà Yahoo Messenger còn phổ biến, dân Linux thường chat Yahoo bằng một phần mềm "nhiều trong một" tên là Pidgin (ngoài Yahoo ra, còn có thể chat cùng lúc với Google Hangout, Facebook Messenger). Phần mềm này có khả năng thú vị là nhận biết khi nào máy bạn đang có mạng, rớt mạng để hiện chỉ thị tương ứng (trạng thái màu xám, các avatar bạn bè bị phủ màu xám). Khi có mạng trở lại thì phần mềm này sẽ tự đổi trạng thái, tự đăng nhập vào các dịch vụ chat và cập nhật danh sách bạn bè. Để nhận biết tình trạng mạng, nó không chơi trò cơ bắp là liên tục kết nối đại vào server nào đấy. Thay vì vậy nó trao đổi với một phần mềm khác tên là NetworkManager. Khi rớt mạng hoặc có mạng, NetworkManager sẽ thông báo trên đường D-Bus và các phần mềm khác "đăng ký" vào D-Bus sẽ nhận được tin.

Đối với những người cần dùng thiết bị USB-3G (như cục D-Com 3G của Viettel chẳng hạn), trên Linux cũng có một phần mềm tên là ModemManager, chạy ngầm để khai thác thiết bị này, ví dụ như chọn sóng của nhà mạng nào, nhập username, password để quay số vào nhà mạng đó, bật sang chế độ data, gửi tin nhắn SMS v.v. ModemManager cũng cho phép giao tiếp qua D-Bus. Chẳng hạn khi cắm thiết bị vào thì danh mục của Network Manager sẽ xuất hiện mục để kết nối mạng 3G, hoặc bạn có thể viết ứng dụng riêng để gửi tin nhắn SMS, lấy các danh bạ lưu trong SIM, tất cả bằng việc giao tiếp với ModemManager qua D-Bus.

...


Nâng cấp Debian cho BeagleBone Black

BeagleBone Black khi bán ra thường được cài sẵn Debian 7 (Wheezy). Đây là phiên bản quá cũ (phát hành 2013) nên các phần mềm đi theo nó thường không đáp ứng đủ nhu cầu. Ví dụ tại AgriConnect, tôi viết phần mềm để chạy trên BeagleBone, dùng ngôn ngữ Python, cần những feature của Python 3.5 trở lên. Thế nhưng trong repository của Debian 7 chỉ có Python 3.2. Việc cài Python từ source code thì hơi bất tiện vì quá trình biên dịch khá nặng trong khi sức mạnh CPU của BeagleBone thì có hạn. Bởi vậy, tốt hơn thì nên nâng cấp Debian để sử dụng phần mềm, thư viện mới hơn từ repo của nó. Ví dụ, Debian 8 (Jessie) thì có Python 3.4, Debian 9 (Stretch) thì có Python 3.5.

Để nâng cấp Debian thì tôi thường lấy image từ https://rcn-ee.com/rootfs/. Để ghi image ra thẻ nhớ thì tôi không dùng dd, mà dùng bmaptool để cho tốc độc cao hơn và biết quá trình ghi tới đâu.

Khi nâng cấp Debian thì có một điều cần lưu ý là nên nâng cấp từng bước, từ 7 lên 8, 8 lên 9, chứ không nên nhảy cóc từ 7 lên 9. Lí do là bị vướng bootloader và tính năng bật tắt cape của BeagleBone.

Hiện nay, trên https://rcn-ee.com/rootfs/ không còn image Debian 8 nữa. Tôi đã kịp giữ lại một bản sao ở đây: http://quan.hoabinh.vn/Downloads/BeagleBone/Debian-2016-04/.


My packages store for BeagleBone running Debian 9

I'm building IoT gateway based on BeagleBone Black at the startup AgriConnect, with Python as the primary programming language.

When the application grows complex, the board shows to be weak. We cannot find stronger board than BeagleBone, so the only option is to try to make our app run lighter. We try to adopt latest Python version, now is 3.6, to take advantage of optimization work in them. The latest Debian image for BeagleBone is stretch (Debian 9), which doesn't include Python 3.6 in its repository.

There are some backport packages of Python 3.6 for Debian 9, but only for amd64 arch. Fortunately they provide a build script. I can use it to build for armhf arch, which is in BeagleBone boards.

How to build for armhf? The board is weak, we should not run the build process directly on BeagleBone. It can take some days!