2023年6月2日 星期五

使用 py2c 出現 Python.h : 沒有此一檔案或目錄的問題

最近在臉書看到有人提到 py2c 這個程式 (是一個 bash script), 它可以將 Python 程式翻成 C++ 程式, 然後就可以用 C++ 編譯器編譯成可執行檔, 其大小比用 pyinstaller 打包還要小得多, 且可以增加逆向工程還原的難度. 我根據下面這篇文章在 Mapleboard 的 Ubuntu Linux 作業系統下測試時卻出現 "Python.h : 沒有此一檔案或目錄的問題" 錯誤, 尚不知原因, 先把過程記下來. 



1. 安裝 Cython3 :  

one@LX2438:~$ sudo apt install cython3    
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
建議套件:
  cython-doc
下列【新】套件將會被安裝:
  cython3
升級 0 個,新安裝 1 個,移除 0 個,有 152 個未被升級。
需要下載 1,306 kB 的套件檔。
此操作完成之後,會多佔用 6,393 kB 的磁碟空間。
下載:1 http://ports.ubuntu.com jammy/universe arm64 cython3 arm64 0.29.28-1ubuntu3 [1,306 kB]
取得 1,306 kB 用了 3s (492 kB/s)   
選取了原先未選的套件 cython3。
(讀取資料庫 ... 目前共安裝了 288142 個檔案和目錄。)
正在準備解包 .../cython3_0.29.28-1ubuntu3_arm64.deb……
解開 cython3 (0.29.28-1ubuntu3) 中...
設定 cython3 (0.29.28-1ubuntu3) ...


2. 下載 py2c :  

到 GitHub 下載 py2c 這個 bash script :


此程式內容如下 : 

#!/bin/bash

if [ -z $1 ];then
printf "Usage: \n\t$0 [python source file][swtich] 1: To C code 2: to bytecode 3: to C and bytecode\n"
exit 0
fi

source_file=$1
tag=$2

fn_ext=$(echo ${source_file} | awk -F '.' '{print $2}'| tr -d '\r\n')
if [ -z ${fn_ext} ]; then
        fn=${source_file}
elif [ ${fn_ext} == "py" ]; then
fn=$(echo ${source_file} | awk -F '.' '{print $1}')
fi

if [ ${tag} -eq 1 ]; then
printf "Transfer python source to C.\n"
cython3 --embed -o ${fn}.c ${source_file}
elif [ ${tag} -eq 2 ]; then
printf "Transfer python source to bytecode.\n"
gcc -Os -I /usr/include/python3.6m -o ${fn} ${fn}.c -lpython3.6m -lpthread -lm -lutil -ldl
elif [ ${tag} -eq 3 ]; then
printf "Transfer python source to C sode and bytecode\n"
cython3 --embed -o ${fn}.c ${source_file}
gcc -Os -I /usr/include/python3.6m -o ${fn} ${fn}.c -lpython3.6m -lpthread -lm -lutil -ldl
fi
printf "Transfer End\n"

將此程式貼到 nano 存成 py2c 檔 : 

one@LX2438:~$ nano py2c    

用 chmod 指令將其權限改為可執行檔後複製到 /usr/bin/local 下 :

one@LX2438:~$ chmod 777 py2c   
one@LX2438:~$ cp py2c /usr/local/bin      

輸入 py2c 會顯示程式用法 :

one@LX2438:~$ py2c   
Usage: 
/usr/local/bin/py2c [python source file][swtich] 1: To C code 2: to bytecode 3: to C and bytecode

亦即指令的格式為 :

py2c 原始程式.py 選項  

選項的值有 1, 2, 3 三個, 1 是將 Python 程式轉成 C 程式; 2 是轉成可執行的 byte code; 3 是轉成 C 程式與可執行的 byte code.

所以我寫了一個 Python 測試程式 helloworld.py :

#helloworld.py
print('Hello World!)

但執行 py2c 卻出現錯誤 : 

one@LX2438:~$ py2c helloworld.py 3    
Transfer python source to C sode and bytecode
/home/one/.local/lib/python3.10/site-packages/Cython/Compiler/Main.py:369: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /home/one/helloworld.py
  tree = Parsing.p_module(s, pxd, full_module_name)
helloworld.c:6:10: fatal error: Python.h: 沒有此一檔案或目錄   
    6 | #include "Python.h"
      |          ^~~~~~~~~~
compilation terminated.
Transfer End

我找到下面這篇文章 :


說是要安裝 python3-dev 才行, 但我安裝後還是一樣 :

one@LX2438:~$ sudo apt-get install python3-dev   
正在讀取套件清單... 完成
正在重建相依關係... 完成  
正在讀取狀態資料... 完成  
python3-dev 已是最新版本 (3.10.6-1~22.04)。
python3-dev 被設定為手動安裝。

目前暫時無解先擱著, 有空再研究. 



2023-06-04 補充 :

我今天用 ChatEverywhere 查詢 AI 對此問題的解法 : 

Q : 我使用 PY2C 時出現 "Python.h : 沒有此一檔案或目錄的問題" 錯誤, 這要如何解決?
A : 您好,這個錯誤通常是因為編譯器無法找到 Python.h 標頭文件所致。
為了解決這個問題,您可以嘗試以下幾個步驟:
確保您已經安裝了 Python 開發套件。在 Linux 上,您可以使用以下命令安裝:

sudo apt-get install python-dev

確保您的編譯器可以找到 Python.h 標頭文件。您可以在編譯器命令中添加以下選項:

-I/usr/include/python2.7/

請注意,上面的路徑可能因您的系統而異,請確保路徑正確。

Q : 請幫我解釋一下這個 bash shell 程式
A : 這個程式是一個 shell 腳本,用於將 Python 程式轉換成 C 語言代碼或字節碼。該腳本接受兩個參數:Python 源代碼文件的路徑和轉換類型。轉換類型可以是以下三種之一:

1. 將 Python 源代碼轉換為 C 語言代碼。
2. 將 Python 源代碼轉換為字節碼。
3. 同時將 Python 源代碼轉換為 C 語言代碼和字節碼。

該腳本使用了以下命令:

1. `cython3`:用於將 Python 代碼轉換為 C 語言代碼。
2. `gcc`:用於編譯 C 語言代碼並生成字節碼。

該腳本還使用了以下選項:

1. `--embed`:用於將 Python 解釋器嵌入到生成的 C 語言代碼中。
2. `-I`:用於指定 Python 開發套件的頭文件路徑。
3. `-o`:用於指定生成的 C 語言代碼或字節碼的輸出文件名。
4. `-l`:用於指定需要連接的庫文件。

該腳本的具體功能如下:

1. 檢查是否提供了 Python 源代碼文件的路徑,如果沒有,則輸出用法信息並退出。
2. 從提供的 Python 源代碼文件的路徑中獲取文件名和擴展名。
3. 如果文件擴展名為 `.py`,則使用文件名作為 C 語言代碼或字節碼的輸出文件名。
4. 根據提供的轉換類型,執行相應的轉換操作。
5. 輸出轉換結束信息。

希望這可以幫助您理解這個程式的功能。如果您有任何問題,請隨時提出。

Q : 編譯器命令中添加的選項怎是 python 2, 我用的是 python 3
A : 對於 Python 3,您可以使用以下命令安裝相應的開發套件:
在 Debian/Ubuntu 系統上:

sudo apt-get install python3-dev

在編譯器命令中,您需要將路徑 /usr/include/python3.6m 中的版本號替換為您系統上安裝的 Python 版本號。例如,如果您的系統上安裝的是 Python 3.8,則路徑應為 /usr/include/python3.8。

沒有留言 :