原文地址:
https://blog.52sox.com/shi-yo...
前言
真的好久沒有分享技術文章了,主要是因為自己寫的文章太過於小眾,沒想到自己竟然會分享這樣一篇文章。這麼一篇濃縮了自己多年來專案開發的實戰經驗。
不得不說,Python是一門很不錯的程式語言。有時候,為了專案程式碼安全考慮,會嘗試將一些原始碼使用Python提供的C API的方式進行編寫,再將其編譯為Python模組的方式,從而在Python中直接呼叫。
編譯的一些技巧
對於Python的C API編寫的程式碼,如果快速將其生成為Python對應的擴充套件庫,如Linux下的.so
或Windows下的.pyd
。
主要有如下一些方法:
- 使用setuptools模組
- 使用scikit-build模組
- 使用cmake
實際上這些方法經常是在一起使用的。
對於手動編寫setup.py
檔案,指定對應的要引入的標頭檔案及連結庫,對於中大型專案是不推薦的。
setuptools方式
在此之前,先使用如下的方式先生成1個C原始檔:
pip install pyd-tpl
pyd-tpl hello
該模組是自己編寫用於快速生成Python的C擴充套件檔案的一個庫。安裝完成後,我們呼叫pyd-tpl
命令會在當前目錄下生成1個hello.c
原始檔及setup_hello.py
檔案。
我們可以直接執行如下的方式進行編譯並生成1個hello模組:
python setup_hello.py
這是第1種使用setuptools生成模組的方式。下面主要介紹後面兩種方式。
scikit-build方式
首先我們執行下面的命令安裝對應的庫:
pip install scikit-build cmake
由於scikit-build依賴於cmake,我們可以直接使用pip的方式安裝該工具。
安裝完成後,接著我們在setup.py
中編寫如下的程式碼:
from skbuild import setup
之後在專案目錄下新建1個CMakeLists.txt
,其內容如下:
cmake_minimum_required(VERSION 3.11.0)
project(hello VERSION 0.1.0)
find_package(PythonExtensions REQUIRED)
add_library("${PROJECT_NAME}" MODULE hello.c)
python_extension_module("${PROJECT_NAME}")
install(TARGETS hello LIBRARY DESTINATION hello)
這裡我們設定我們專案的名稱為hello,通過使用cmake提供的find_package
指令尋找Python的擴充套件。之後通過add_library
對hello.c
檔案編譯,從而生成以專案名稱命名的模組。
接著還需要在專案目錄下創見1個pyproject.toml
的檔案,其內容如下:
[build-system]
requires = ["setuptools", "wheel", "scikit-build", "cmake", "ninja"]
之後我們執行如下的命令即可實現整個過程的自動編譯:
python setup.py build
不過這種方式有個不好的地方在於,如果系統無法正常識別你的編譯器,比如在Windows下我使用的是Visual Studio 2015,它並沒有很好的識別出來。只能在Visual Studio 2015工具提供的選單視窗下執行才行。
其過程如下圖所示:
cmake原生方式
在cmake版本3.12
開始,提供了1個非常好用的Python_add_library
命令,詳情可以參考。藉助該命令,我們可以快速生成Python的C擴充套件。
我們只需要在上述CMakeLists.txt
中的內容進行如下的修改:
cmake_minimum_required(VERSION 3.12.0)
project(hello VERSION 0.1.0)
find_package (Python3 COMPONENTS Development)
include_directories(${Python3_INCLUDE_DIRS})
Python3_add_library(hello MODULE hello.c)
該命令語法與add_library
命令一樣。在這裡,我們使用的是Python3,因此在find_package
命令中指定的使用Python3。
之後在Windows下建立1個build目錄,並進入該目錄中再執行如下命令:
mkdir build
cd build
cmake -G "Visual Studio 14 2015" -A x64 ..
cmake --build . --config Release
而對於Linux將相應的命令修改為:
cmake ..
make
通過cmake工具,這樣我們就可以輕鬆地生成對應Python的hello.pyd
及hello.so
的C擴充套件。
後語
實際上,對於生成Python的C擴充套件還有1種方式就是將cmake與setup.py
檔案結合,通過setup.py
檔案中setup函式的cmdclass
引數指定自定義1個cmake編譯類。
實際上,在實際專案開發中,真的沒必要搞得這麼複雜,將1個非常簡單的問題複雜化是得不償失的。
這裡就不展開介紹了,使用上述3種方法即可很輕鬆解決Python的C擴充套件編譯的問題。其中最推薦使用第3種方式。