前往
大廳
主題

Windows pybind11安裝流程跟紀錄一些眉角

玥宵 | 2024-02-02 18:03:21 | 巴幣 0 | 人氣 134

在建pybind11的時候遇到滿多問題的,網路上Windows的文也比較少,在這邊紀錄一下。這邊主要是以C++作為主程式呼叫Python,反過來的話比較容易一點就不另外寫了

大致上的流程是參考以下影片:
(Setting up CMake, Pybind11 and QtCreator [Part 3A, Understand & Code a Kalman Filter])
不過影片中的OS是linux,因此有些地方需要做一些調整

1:05秒左右的touch那一行Windows沒有,直接在vscode手動建CMakeLists.txt就好
1:30秒左右的1、2行要對調
4:30秒左右複製到wrappers.cpp的時候include pybind11應該還找不到,之後需要再加一下路徑
5:30秒左右的Cmake ..為Linux指令,Windows需要另外裝mingw64,可以參考以下這篇: https://blog.csdn.net/weixin_49001740/article/details/122724265 (Windows10安装MinGW-w64)

Cmake的安裝可以參考以下這篇

裝好之後用這個指令cmake -G "MinGW Makefiles" .. (要先cd到build資料夾再用)。後面的make要改成mingw64/bin中的mingw32-make,應該就可以編譯成功了(cmake跟mingw64的bin資料夾都要加到系統變數的PATH)

另外,剛剛影片中的CMakeLists.txt中有
include_directories(thirdParty/eigen)
add_subdirectory(thirdParty/pybind11)

多加幾行(上面三行如果都照著影片裝的話應該會是一樣的,target_link_libraries那兩行第三個參數需要找到自己的pythonXX.lib的位置,以下均為我電腦的位置)
include_directories(D:/anaconda3/include)
include_directories(thirdparty/pybind11/include/pybind11)
add_executable(test wrappers.cpp)
target_link_libraries(kf_cpp PRIVATE D:/anaconda3/libs/python39.lib)
target_link_libraries(test PRIVATE D:/anaconda3/libs/python39.lib)

這樣就可以直接include,把以下程式加入wrappers.cpp檔案中
#include <Python.h>
#include <pybind11.h>
#include <embed.h>
#include <iostream>

namespace py = pybind11;

int main() {
py::scoped_interpreter python;

py::module sys = py::module::import("sys");
py::print(sys.attr("path"));

py::module t = py::module::import("python檔名不用加.py");
py::object var = t.attr("add")(1,2); // 不管python funtion回傳什麼都可以用py::object接
int res = py::cast<int>(var); // 利用py::cast來將object轉成c++的type
std::cout << res << std::endl;

system("pause");
}

影片中的PYBIND11_MODULE是給以python為主程式來呼叫C要用的,如果要以C/C++作為主程式不需要,
然後在build資料夾建立另外一個.py檔案(不能在同一個資料夾,.cpp檔會找不到檔案),加入以下程式
def add(i, j):
print("hello,pybind11")
return i + j

用mingw32-make編譯,如果檔案無法建立或是建立出來但執行了直接跳掉的話就要參考這個網站 https://stackoverflow.com/questions/69550830/init-fs-encoding-failed-to-get-the-python-codec-of-the-filesystem-encoding (init_fs_encoding: failed to get the Python codec of the filesystem encoding)

在系統變數選新增,變數名稱: PYTHONHOME,變數值: python.exe的位置(ex: D:\anaconda3\)
再新增一個變數名稱: PYTHONPATH,變數值: site-packages的位置(ex: D:\anaconda3\Lib\site-packages)

到這邊.cpp檔中的include<Python.h>跟<pybind11.h>應該都還是紅底線的狀態,不過實際上是找的到的,如果.exe檔可以順利執行就可以忽略這個error了

這樣應該就可以順利執行印出類似以下結果了
['', 'D:\\anaconda3\\Lib\\site-packages', 'D:\\anaconda3\\python39.zip', 'D:\\anaconda3\\DLLs', 'D:\\anaconda3\\lib', 'C:\\Users\\USER\\Desktop\\c++_with_python\\build', 'D:\\anaconda3', 'D:\\anaconda3\\lib\\site-packages\\win32', 'D:\\anaconda3\\lib\\site-packages\\win32\\lib', 'D:\\anaconda3\\lib\\site-packages\\Pythonwin']
3





# 以下內容為測試虛擬環境的紀錄,沒有特別需求直接使用本地端的話就可以直接跳過了(可能有其他更好的方法我不知道,至少以下方法在我的電腦測試過能夠運作)

此方法須先下載anaconda3(https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&O=D),我使用的是2022.10的版本。

因為高於python高於3.10的話會有Fatal Python error: init_fs_encoding: failed to get the Python這個bug,我目前是沒有找到解法因此選擇安裝3.9的python。

另一方面是因為tensorflow只支援gpu到2.6.0版而已,對應的python是3.6-3.9(最下面有版本對應:https://www.tensorflow.org/install/source_windows?hl=zh-tw),同時在安裝cuda以及cuDNN的時候也要記得注意對應tensorflow的版本(接下來有可能還會遇到numpy、h5py等等的問題,基本上都是降版本就可以了)。

安裝anaconda網路上有很多教學,其中比較要注意的應該只有若安裝時沒有勾選自動添加路徑的話要把
D:\anaconda3
D:\anaconda3\Scripts
D:\anaconda3\Library\bin
D:\anaconda3\Library\include
這四個路徑加到環境變數裡面,若是之前已經建立好其他的PYTHONPATH以及PYTHONPATH的話也請更改到anaconda的路徑。

接著打開Anaconda Prompt,應該會當前路徑前面會有一個(base),這時就可以進行下一步,輸入:
conda create --name env_name python==3.9
env_name的部分為自己取的虛擬環境名稱,python版本也可以隨意挑選,不過就像上面提到的,如果想要使用tensorflow2.6.0的話必須要在3.6-3.9之間。

建立好後就可以使用下面指令進入虛擬環境
activate env_name
這時應該就會發現前面的小括號變成 (env_name)了,表示虛擬環境創立且激活成功。

接著把
include_directories(D:/anaconda3/include)
target_link_libraries(kf_cpp PRIVATE D:/anaconda3/libs/python39.lib)
target_link_libraries(test PRIVATE D:/anaconda3/libs/python39.lib)
改成對應的虛擬環境位置。

確認目前在虛擬環境後,在anaconda prompt中打入
set "PYTHONPATH=D:\anaconda3\envs\alphazero\Lib\site-packages"
set "PYTHONHOME=D:\anaconda3\envs\alphazero"
路徑部分轉換成自己的,以上為範例。

使用上面的set PYTHONPATH以及PYTHONHOME之後conda會無法使用,這時候只要重新set回原本anaconda的路徑就可以了。
不過如果以上兩系統變數是在base anaconda的環境下的話引入的module也會從base環境下的site-package去找,因此很常會有明明就有安裝但是卻找不到、或者是安裝的版本跟想像中的不一樣等等的情況發生。

接著cd到前面建立的build資料夾,把build中的檔案刪除到只留下.py檔,在prompt中輸入
cmake -G "MinGW Makefiles" ..
mingw32-make
重新建立一次build資料夾內的檔案,因為當前這些檔案都還是之前建立的,使用的是之前的路徑,會與現在的python路徑產生衝突。

若cmake的部分有報錯的話很有可能是環境變數或者是剛剛set path等等的問題,如果都不是的話則可能是曾經有卸載、重載過anaconda而導致環境沒有很乾淨。

如過以上步驟都順利完成的話在prompt中輸入
python test.exe
應該就可以順利跑出結果了。



# 2024/2/25
訓練的時候一直跳出tensorflow不支持AVX2指令集的問題,然後就找到了這個
https://github.com/fo40225/tensorflow-windows-wheel
而且他的tensorflow gpu提供到2.9.0的版本,python同樣是3.9,cuda以及cudnn可以按照
的方法安裝相對應的版本。

假設要下載版本2.9.0且支持AVX2指令集的tensorflow的話就選2.9.0/py39/CPU+GPU,然後選擇cuda117cudnn8avx2,下載完後解壓縮001檔,在想要安裝的環境下輸入
pip install tensorflow-2.9.0-cp39-cp39-win_amd64.whl 就可以囉。

如果他會跳一些問題的話可以先試試看pip uninstall tensorflow在重載一次tensorflow==2.9.0試試,
如果是其他版本的話可能會有找不到cuda/bin中一些檔案的問題,大部分應該是tensorflow與cuda的版本對不上,這時以tensorflow官方文檔中的對應版本來重新下載tensorflow或是cuda、cudnn應該就沒有問題了。
我這邊的狀況是因為桌機比較久,NVIDIA是456.71版本的,因此我載了2.3.0\py38\CPU+GPU\cuda110cudnn8avx2,不過當我要訓練模型的時候就跳出了找不到一堆檔案的warning,如果不解決的話會沒辦法使用GPU,去官方文檔看了一下之後發現cuda11.0、cudnn8.0對應的是tensorflow-gpu 2.4.0,因此我就把tensorflow改成2.4.0之後就可以順利使用GPU了。

如果是在base環境中裝的,執行時遇到 'WindowsPath' object has no attribute 'read_text'的話輸
pip uninstall pathlib

如果是平常測試或是改程式只會在自己點腦上跑的話用虛擬環境可以避免一些衝突的問題,不過如果你的程式需要像是將執行檔連接到某某平台之類的,這時候如果使用虛擬環境的話可能會產生找不到Module的問題,也許可以在CmakeList.txt中加入一些東西來解決這個問題,不過如果不太想要或是沒辦法處理這些問題的話可能直接在base環境下再裝一次tensorflow比較快。

創作回應

更多創作