我們編寫的程序源代碼,或者下一個小的腳本文件需要對外發布時,我們有時候不想讓別人能輕易地看到我們的源碼,可以將其編譯成pyd形式地進行外發,pyd相對於pyc和pyo編譯文件,他們兩種文件形式差不多,也很容易被反編譯,pyd格式是D語言(C/C++綜合進化版本)生成的二進制文件,實際也是DLL文件,這種格式文件目前好像是沒有可以反編譯的消息,只能反匯編。這種文件區別於打包成exe是它生成的pyd文件還可以是原來項目的目錄結構,對於項目開發者來說釋放出去之后出現問題也方便定位。廢話多說,上代碼比較。
以獲取當前工作目錄的代碼為例,我們對比一下pyc文件和pyd文件的區別
源碼 假定文件是current_path.py
1 import time 2 import os 3 4 while 1: 5 time.sleep(1) 6 print(os.getcwd())
在該文件的目錄下打開python解釋器執行
可以看到在當前目錄下生成一個__pychache__的文件夾,打開會有一個同名的pyc文件
打開之后,
還是多少能看到點源碼的,這個就違背了不想讓人看到源碼的初衷了,我們再來看下生成的pyd文件,
這就很nice了。下面介紹具體方法:
1、安裝Cython,python下很簡單,pip3 install cython 即可
2、准備源文件、即上面的current_path.py
3、准備打包文件 set_up.py 內容如下
from distutils.core import setup from Cython.Build import cythonize setup(ext_modules=cythonize("set_up.py"))
4、在當前目錄下執行
python set_up.py build_ext --inplace
5、報錯 Unable to find vcvarsall.bat
解決辦法 安裝Visual studio 官網下載社區版即可安裝時選擇Python開發進行安裝(下圖是找的,自己安裝的時候忘記截圖了,懶得截了)
python setup.py build_ext --inplace
在超過二級目錄的時候會額外多一級目錄,目前還沒有好的辦法解決,希望看到這例的讀者能提供一個好的建議。再有就是如果項目中出現了同名的set_up.py時,要記得單獨編譯一下。
將其重命名,去掉 cp37-win_amd64.,將其移動到源文件位置刪除源文件,就可以使用了,但是不是直接執行該文件,而是去另外一個文件例去導入該文件的函數或者類,執行另外一個py文件,這時候就執行成功了。跟正常的源文件一樣,這時候就滿足了需求。
上述是單個打包成pyd文件,但是批量打包的話這樣做很難受,我看到的只是批量生成pyc文件的命令,但是沒有批量生成pyd文件的命令,於是自己就寫了一段程序供大家參考,代碼如下 create_pyd_file.py
#!/usr/bin/env python # -*- coding:utf-8 -*- # @time: 2021/5/26 14:17 # @File: create_pyd_file.py import os import shutil import time import sys def func(path): folder_path = os.path.dirname(path) file_path = os.path.split(path)[1] os.chdir(folder_path) with open('setup.py', 'w') as f: f.write('from setuptools import setup\n') f.write('from Cython.Build import cythonize\n') f.write('setup(\n') f.write("name='test',\n") f.write("ext_modules=cythonize('%s')\n" % file_path) f.write(")\n") os.system('python setup.py build_ext --inplace') filename = file_path.split('.py')[0] time.sleep(2) # 這里的cp37-win_amd64需要注意一下,這個是依據python解釋器類型以及windows版本生成的,建議是單個生成一個pyd文件然后相應修改一下 os.rename('%s\\%s.cp37-win_amd64.pyd' % (folder_path, filename), '%s\\%s.pyd' % (folder_path, filename)) # 這個是刪除py源文件,測試的時候可以先注釋掉查看效果 os.remove('%s.c' % filename) build_folder_path = os.path.join(folder_path, 'build') # 刪除掉生成的build文件夾 shutil.rmtree(build_folder_path) os.remove('setup.py') os.remove(file_path) def get_all_file(path): for root, dirs, files in os.walk(path): for name in files: if name.endswith(".py"): file_path = os.path.join(root, name) func(file_path) paths = sys.argv[1] get_all_file(paths)
調用的方法是在該文件當前路徑下執行 加上項目的絕對路徑 比如
python create_pyd_file.py D:\python_demo\demo
測試的時候在windows以及ubuntu上二級目錄都可以編譯成pyd文件並替換到原來的位置 現在有點問題的就是再深層級的目錄就出現問題了,原因是這條命令
更多精彩,可以關注樓主的公眾號,
最全面的django面試題總結: 回復django面試題即可獲取, pycharm供給激活壓縮包, 回復pycharm破解包即可獲取,破解步驟在我的這一篇博客(點我直達)已經破解百次, 屢試不爽.
以及其他樓主精心打造的原創文章,歡迎各位來訪.