python 讓原始碼更安全之將py編譯成so

2021-08-21 03:55:40 字數 4361 閱讀 8957

python:讓原始碼更安全之將py編譯成so

應用場景

python是一種物件導向的解釋型計算機程式語言,具有豐富和強大的庫,使用其開發產品快速高效。

python的解釋特性是將py編譯為獨有的二進位制編碼pyc檔案,然後對pyc中的指令進行解釋執行,但是pyc的反編譯卻非常簡單,可直接反編譯為原始碼,當需要將產品發布到外部環境的時候,原始碼的保護尤為重要.

準備工作

環境是可為linux/centos,我windows10本地是bash on ubuntu on windows,用起來很方便,命令列打bash即進入命令列

思路是先將py轉換為c**,然後編譯c為so檔案

所以要安裝以下內容

python 安裝:cython

pip install cython

linux 安裝:python-devel,gcc

yum install python-devel

yum install gcc

初步編譯

在testing資料夾下有your_file.py檔案待編譯,內容如下

#

-* -coding: utf-8 -* -

__author__ = '

arvin

'class

test:

defsay(self):

print

'hello

'

新建setup.py,內容如下

from distutils.core import

setup

from cython.build import

cythonize

setup(ext_modules = cythonize(["

your_file.py

"]))

在bash中執行

cd testing

python setup.py build_ext

執行後會生成build資料夾,如下,lib.linux-x86_64-2.7下就是我們想要的.so檔案

現在so檔案就可以像普通py檔案一樣匯入了

cd build/lib.linux-x86_64-2.7/python

from your_file import test

test().say()

整合編譯最新**github:

做了以下內容:

1.資料夾編譯

2.刪除編譯出的.c檔案

3.刪除編譯的temp資料夾

#

-* -coding: utf-8 -* -

__author__ = '

arvin

'import

sys, os, shutil, time

from distutils.core import

setup

from cython.build import

cythonize

starttime =time.time()

currdir = os.path.abspath('.'

)parentpath = sys.argv[1] if len(sys.argv)>1 else

""setupfile= os.path.join(os.path.abspath('

.'), __file__

)build_dir = "

build

"build_tmp_dir = build_dir + "

/temp

"def getpy(basepath=os.path.abspath('

.'), parentpath='', name='', excepts=(), copyother=false,delc=false):

"""獲取py檔案的路徑

:param basepath: 根路徑

:param parentpath: 父路徑

:param name: 檔案/夾

:param excepts: 排除檔案

:param copy: 是否copy其他檔案

:return: py檔案的迭代器

"""fullpath =os.path.join(basepath, parentpath, name)

for fname in

os.listdir(fullpath):

ffile =os.path.join(fullpath, fname)

#print basepath, parentpath, name,file

if os.path.isdir(ffile) and fname != build_dir and

not fname.startswith('.'

):

for f in

getpy(basepath, os.path.join(parentpath, name), fname, excepts, copyother, delc):

yield

f

elif

os.path.isfile(ffile):

ext = os.path.splitext(fname)[1]

if ext == ".c"

:

if delc and os.stat(ffile).st_mtime >starttime:

os.remove(ffile)

elif ffile not

in excepts and os.path.splitext(fname)[1] not

in('

.pyc

', '

.pyx'):

if os.path.splitext(fname)[1] in('

.py', '

.pyx

') and

not fname.startswith('__'

):

yield

os.path.join(parentpath, name, fname)

elif

copyother:

dstdir =os.path.join(basepath, build_dir, parentpath, name)

ifnot

os.path.isdir(dstdir): os.makedirs(dstdir)

shutil.copyfile(ffile, os.path.join(dstdir, fname))

else

:

pass

#獲取py列表

module_list = list(getpy(basepath=currdir,parentpath=parentpath, excepts=(setupfile)))

try:

setup(ext_modules = cythonize(module_list),script_args=["

build_ext

", "

-b", build_dir, "-t"

, build_tmp_dir])

except

exception, ex:

print

"error!

", ex.message

else

: module_list = list(getpy(basepath=currdir, parentpath=parentpath, excepts=(setupfile), copyother=true))

module_list = list(getpy(basepath=currdir, parentpath=parentpath, excepts=(setupfile), delc=true))

ifos.path.exists(build_tmp_dir): shutil.rmtree(build_tmp_dir)

print

"complate! time:

", time.time()-starttime, '

s'

注意問題1.編譯後執行需要相同的python版本和編碼

2.py中使用__file__內建變數的檔案編譯後呼叫時會出問題,暫時沒有解決,還需要使用pyc代替

3.使用時注意許可權控制

Python原始碼學習 之 Python直譯器

include 公有 標頭檔案 lib python編寫的模組 modules c實現的模組 objects 內建物件型別的實現 pc windows下構建python的工程檔案 pcbuild parser 直譯器的 parser tokenizer input handling python 直...

《Python原始碼剖析》之 str

定義 typedef struct pystringobject 說明 pyobject var head pystringobject是變長物件,比定長物件多了乙個ob size欄位 ob shash 儲存字串的hash值,如果還沒計算等於 1 當string hash被呼叫,計算結果會被儲存到這...

Python原始碼學習 之bytecode

原始碼 py檔案 或 字串 位元組碼 可快取在 pyc 結果 pythonx.dll libpythonx.x.a pythonx.dll libpythonx.x.a py compilestring pyeval eval compile eval 中通過import使用到的.py檔案會自動編譯...