[Chia sẻ - Nhập môn] Biên dịch code Python (.pyx) thành .pyd bằng Cython và đóng gói .exe không cần cài Python (2 người xem)

Người dùng đang xem chủ đề này

Kiều Mạnh

I don't program, I beat code into submission!!!
Tham gia
9/6/12
Bài viết
5,705
Được thích
4,193
Giới tính
Nam
Mình vốn quen làm việc chính với Delphi/C++ Builder và Go để viết add-in Excel,
nhưng gần đây có thử nghiệm thêm hướng dùng Python để xử lý logic, sau đó biên dịch thành mã máy (không phải file .py gốc) nhằm mục đích:


  • Tăng tốc độ xử lý so với chạy Python thông thường (interpreter thuần)
  • Ẩn source code gốc - không muốn phát tán file .py để người khác đọc/copy logic
  • Có thể đóng gói thành .exe chạy độc lập, không cần máy đích cài Python

Sau vài lần thử, mình có 1 quy trình nhỏ chạy ổn, chia sẻ lại để các bác tham khảo, đồng thời rất mong nghe thêm cách các bác đang làm - chắc chắn còn nhiều hướng hay hơn mình chưa biết.

Quy trình mình đang dùng​

Bước 1 - Viết logic bằng Cython (.pyx)

File .pyx viết gần giống hệt Python thường, chỉ khác đây là biến thể có thể biên dịch ra C:


def cong(a, b):
return a + b

def tinh_gia_sau_giam(gia_goc, phan_tram_giam):
if phan_tram_giam < 0 or phan_tram_giam > 100:
raise ValueError("Phan tram giam phai tu 0 den 100")
return gia_goc * (1 - phan_tram_giam / 100)


Bước 2 - Biên dịch .pyx → .pyd

Cần cài Cython + Visual Studio Build Tools (chỉ cần workload "Desktop development with C++", không cần cài cả bộ Visual Studio). Sau đó chạy:
python setup.py build_ext --inplace
Kết quả ra file xu_ly_logic.pyd - đây thực chất là 1 file DLL đã biên dịch thành mã máy x64, không còn là code Python đọc được nữa (khác hẳn .pyc, không decompile ngược ra Python gốc được bằng công cụ thông thường).


Bước 3 - Đóng gói tiếp thành .exe độc lập (không cần cài Python)

Dùng PyInstaller để gộp Python runtime + file .pyd thành 1 file .exe duy nhất:
pyinstaller --onefile --add-binary "xu_ly_logic.pyd;." --name ChuongTrinhDemo main.py

File .exe này copy sang máy khác chạy thẳng, máy đích không cần cài Python.


File đính kèm​


Mình gửi kèm bộ demo đầy đủ trong file zip, gồm:
  • xu_ly_logic.pyd - module đã biên dịch sẵn (5 hàm: cộng, trừ, nhân, chia, tính giá sau giảm)
  • main.py - chương trình demo gọi vào module trên
  • build_exe.bat - chạy tự động lệnh PyInstaller đóng gói .exe
  • run_exe.bat - chạy thử file .exe sau khi build

Ai muốn tự build lại thì cần cài sẵn Python + Cython + PyInstaller + Visual Studio Build Tools trên máy, sau đó chạy build_exe.bat.


Vài điều mình còn băn khoăn, mong các bạn góp ý​

  1. Cách này chỉ hợp khi muốn giấu logic tính toán khỏi Python thuần, nhưng nếu muốn tái sử dụng cho Delphi/VB6/VBA gọi trực tiếp thì file .pyd này lại không dùng trực tiếp được (chỉ export hàm PyInit_... dành riêng cho CPython nạp module, không theo chuẩn C-ABI thường). Các bác nào từng làm việc này có kinh nghiệm gì cross-language giữa Python và Delphi/VBA không?
  2. Có bác nào đã thử dùng Python làm COM server (qua pywin32) để Excel/VBA gọi vào bằng CreateObject chưa? Mình nghe nói cách này khả thi nhưng chưa thử, không rõ độ ổn định và tốc độ thực tế so với add-in Delphi/XLL truyền thống thế nào.
  3. Nếu ai có kinh nghiệm với PyXLL hoặc xlwings để làm add-in hàm số Excel bằng Python thật sự (không qua trung gian DLL/EXE), rất mong chia sẻ thêm góc nhìn, ưu nhược điểm so với cách viết Add-in bằng Delphi/C++ Builder truyền thống.

Cảm ơn các bạn đã đọc, mong nhận được góp ý và các hướng làm khác để mình học hỏi thêm!




File đính kèm: pyd_exe_demo.zip
 

File đính kèm

Đang viết một công cụ nhỏ bằng Delphi tên PyBuildTool để hỗ trợ build dự án Python/Cython trên Windows.

Hiện tool đã làm được:

  • Quét toàn bộ project Python (kể cả thư mục con).
  • Tự biên dịch các file .pyx thành .pyd bằng Cython + MSVC.
  • Tạo bản .pyd để chia sẻ/import trực tiếp.
  • Đóng gói main.py thành một file .exe bằng PyInstaller.
  • Giữ build_cache riêng, còn file rác đưa vào Windows Temp rồi tự dọn sau khi build.
Mục tiêu tiếp theo là tích hợp trực tiếp vào VS Code. Viết mã trong VS Code, bấm Build là PyBuildTool xử lý toàn bộ quy trình phía sau.

1789692991945.png

Qua lúc làm dự án này mới thấy Python có điểm rất mạnh là hệ sinh thái và tốc độ phát triển, nhưng khi phát hành ứng dụng Windows thì vẫn cần thêm các bước build, đóng gói và quản lý môi trường. Mình đang thử gom tất cả các bước đó vào một công cụ duy nhất viết bằng Delphi để dùng cho tiện.

Hình sau là kết quả sử dụng PyBuildTool build dự án Python

1789693848900.png
 
Lần chỉnh sửa cuối:
Cơ bản đã xong Tools biên dịch cho .py sang .pyd ( mã máy sử dụng Cython ) xong ...

xem xét tích hợp vào VS code như Extension sử dụng chung cho mọi Project nữa là xong

Vậy là ngôn ngữ nào có thế mạnh thì sử dụng ngôn ngữ đó viết mã xong liên kết lại thành một hệ thống xử lý cho công việc khi cần thiết

1789954404741.png
 
Thêm link sau cho ai đó sau này có một lựa chọn biên dịch cho Python


AI nó phân tích như sau

View attachment 312675
Nuitka nó đóng gói như rùa bò anh ơi, cũng có thể do máy yếu vì nó có tham số jobs em để 4. Khi đóng gói cùng file python, bằng cython + pyinstaller thì vài phút, dùng Nuitka cả tiếng chưa xong :D
 
Nuitka nó đóng gói như rùa bò anh ơi, cũng có thể do máy yếu vì nó có tham số jobs em để 4. Khi đóng gói cùng file python, bằng cython + pyinstaller thì vài phút, dùng Nuitka cả tiếng chưa xong :D
chính xác như vậy nó đóng gói quá chậm hơn rùa luôn ... nhưng nhập môn Pthon thì nên tìm hiểu hết mọi cái để biết và sử dụng khi cần
Viết tools cơ bản đã xong giờ đang tích hợp vào VS code nữa là xong

1/ file EntrySplitter.exe viết băng py ( vì có nhiều thứ viết ngôn ngữ khác sẽ rất khó nên viết Py luôn )và đóng gói Nuitka

2/ File PyBuildTool.exe là Tools chính khi chạy nó gọi EntrySplitter.exe phân tách entry point để chuyển từ .py sang .pyd

1790074470063.png

3/ Chọn bộ có hai file này cho Tools biên dịch Py sang mã máy nhưng có điều mã máy thật đấy mà không chạy trực tiếp lấy gì ra nhanh

4/ còn ai đó lâu này nói Py siêu nhanh hãy đọc kỹ các dòng sau

Python siêu nhanh thì phải xác định rõ nhanh ở đâu. Nếu Python gọi một DLL C/C++ đã được biên dịch thành mã native và phần nặng nằm hết trong DLL đó, thì tất nhiên phần DLL có thể rất nhanh. Nhưng đó là tốc độ của C/C++, không thể lấy nó để kết luận Python tự thân chạy nhanh như C/C++.

Chưa kể đem PYD/DLL sang máy khác còn phải xét runtime, dependency và các thư viện đi kèm. Chương trình không phải cứ "build ra mã máy" là thành một EXE độc lập chạy trực tiếp như nhau trên mọi máy.

Vậy nên đừng trộn ba chuyện thành một: Python runtime, native code và thư viện/runtime phụ thuộc. Muốn nói "siêu nhanh" thì đưa bài benchmark cụ thể, nói rõ đoạn nào chạy bằng Python, đoạn nào chạy native, overhead gọi qua lớp trung gian bao nhiêu, rồi hãy so với C/C++.

5/ Hôm nay tôi mới thử viết một DLL/PYD bằng Python rồi copy sang máy khác mới thấy nó không phải cứ build xong là mang đi chạy độc lập. Nó còn phụ thuộc vào runtime và các thư viện đi kèm.

Khi chương trình chạy, Python lại phải thông qua các lớp/runtime đó để gọi phần mã native bên dưới. Mỗi lần gọi có overhead, dù một lần có thể rất nhỏ, nhưng gọi hàng trăm nghìn hay hàng triệu lần thì chi phí đó sẽ tích lũy.

Vậy nên nói "Python siêu nhanh" thì phải benchmark cụ thể: đoạn nào thực sự chạy native, đoạn nào chạy qua runtime, overhead mỗi lần gọi là bao nhiêu và tổng thời gian so với C/C++ trực tiếp thế nào.

Nếu phần nhanh nhất cuối cùng là C/C++ nằm bên dưới thì đừng lấy tốc độ của phần đó để nói Python cũng chạy nhanh như C/C++.

Một DLL viết trên Py khi copy qua máy khác phải kèm cả một đống file đi cùng nữa mới chạy được nếu không là tịt
 
Lần chỉnh sửa cuối:

Bài viết mới nhất

Back
Top Bottom