Lưu đọng dữ liệu Iconify để dùng offline

Là một nhà phát triển web, bạn có thể đã biết đến Iconify, một kho dữ liệu icon dành cho web cực kỳ phong phú, tổng hợp từ nhiều bộ khác nhau (FontAwesome, Material Design v.v...) để đưa về một cách sử dụng chung. Tôi cũng không ngoại lệ, cũng sử dụng Iconnify trong nhiều dự án, vì ngoài việc tích hợp dễ dàng vào dự án, Iconify còn cho phép trộn lẫn nhiều bộ, vì nhiều khi hình ảnh mà tôi cần không tồn tại trong bộ này mà chỉ có ở bộ kia (bạn có thể lo ngại việc trộn lẫn khiến phong cách hình ảnh không thống nhất, đành chịu, vì với người không có khả năng thiết kế thì phải chấp nhận thôi).

Để có được ưu điểm kể trên, Iconify không bắt bạn phải đóng gói hết nội dung icon của các bộ cần dùng, mà dùng cơ chế gọi API để lấy về nội dung của icon khi cần (và nội dung này cũng được lưu trữ tạm để khỏi gọi API lại nhiều lần).

icon api

Với phần lớn trường hợp thì cách làm này là ổn, nhưng một số trường hợp thì nó lại gây băn khoăn. Ví dụ với một sản phẩm IoT, khi mà website đó chạy trong mạng nội bộ, để có thể tự hành khi rớt Internet, hoặc được truy cập ở vùng sâu vùng xa nơi điều kiện Internet không tốt, khi việc gọi API lấy nội dung icon có thể thất bại và ảnh hưởng xấu đến giao diện website. Với những trường hợp như thế thì tôi phải tìm cách thu thập nội dung icon và đính kèm theo website, để không phải gọi API nữa.

...

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

Thỉnh thoảng mình có mối duyên ghé mắt qua các dự án Python, 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. Nê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.

Một công cụ hiện đại mà mình hay dùng, và khuyên dùng cho tình huống này là Poetry. Khi bạn cần thêm C vào danh sách phụ thuộc, chỉ cần chạy:

...

Giao diện mới

Hôm nay, sau rất nhiều năm tạo website cá nhân này, tôi mới có một đợt tu sửa giao diện đầu tiên.

new ui

Nhìn qua thì không khác gì mấy với giao diện cũ: vẫn thanh điều hướng màu cam trên đỉnh, với dòng chữ Playground to đùng phía dưới. Thực ra, sự thay đổi lớn nhất là nằm trong code: Đổi framework CSS từ Bootstrap v3 sang TailwindCSS v2, bỏ jQuery và thay bằng AlpineJS. Kết quả lớn nhất của sự thay đổi này là sửa được lỗi thanh điều hướng trong màn hình điện thoại như sau:

Before ...

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.

...

Dùng Python viết hàm xử lý dữ liệu dưới tầng database cho PostgreSQL

Có một bận, tôi ôm trong tay một bộ CSDL của website nọ, với nhiều thông tin danh tính người thật. Để tránh cho dữ liệu danh tính bị lộ, hưởng ứng tinh thần của Luật An Ninh Mạng, tôi quyết định phải làm xáo trộn dữ liệu đó để nó không còn phản ánh danh tính thật nữa. Cụ thể là tôi sẽ ghi thêm vài kí tự bừa bãi vào cột email, cho nó thành email "xạo" hết.

Nói tới nhu cầu này thì cách dễ nhất là viết đoạn code cho nó chạy một vòng lặp, lặp qua các dòng của bảng dữ liệu, tại mỗi dòng lấy ra cột email, ghi nội dung mới vào rồi lưu lại. Cách đó dễ, nhưng hơi cơ bắp, không tinh tế, sẽ chậm khi bảng dữ liệu hơi lớn. Tôi quyết định thử phương án tạo hàm tùy thêm cho hệ CSDL đó, để có thể sửa tất cả trong một câu truy vấn (query) duy nhất, ví dụ:

UPDATE web_users SET email = my_func(email)
...

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:

...

Dùng Flask hay Django?

DjangoFlask là hai cái tên được nhắc đến nhiếu nhất khi nói về web framework của Python, đặc biệt là giữa những người mới bước chân vào thế giới Python. "Dùng Flask hay Django?" cũng là câu hỏi mà tôi hay nghe đi nghe lại trên các diễn đàn trao đổi, hỏi bài. Với kinh nghiệm về 2 thứ này, tôi viết một bài ngắn gọn, mong trả lời trước cho những ai mới chập chững bị "rắn cắn" này.

Flask_vs_Django Image credit: coderseye.com

Về Flask, tôi đã 3 lần sử dụng Flask cho phần mềm của mình. Lần sử dụng đầu tiên, khoảng năm 2013, tôi làm cho một tay nghiên cứu sinh về Big Data, khi anh chàng này viết một phần mềm xử lý dữ liệu lớn (Java + Hadoop) và cần một trang web để làm giao diện điều khiển cho việc chọn dữ liệu nguồn và lấy kết quả về sau khi xử lý. Lần tiếp theo, tôi viết server phân quyền cho cổng login của mạng wifi (có các tên gọi khác là Splash page, Captive Portal, Wifi Marketing), và sản phẩm cuối cùng tôi dùng Flask là để tạo trang blog này (viết lai rai từ 2013 đến nay).

...


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!