Python3 掃描庫(kù)文件并獲取版本號(hào)信息的操作方法
1. 目的
在 C/C++ 開(kāi)發(fā)中使用了第三方庫(kù),具體說(shuō)是 .a
, .lib
, .dll
等文件,想通過(guò) Python 查詢出這些文件中的版本號(hào)信息。
有人可能好奇,這里簡(jiǎn)單消除可能得疑慮:
- 為什么不用源代碼,而用庫(kù)?
因?yàn)閹?kù)文件提供了良好的隔離性,避免了繁雜的編譯選項(xiàng)指定, 避免了潛在的不小心改了代碼導(dǎo)致的不一致
- 為什么不用包管理工具來(lái)設(shè)定和查詢庫(kù)文件的版本?
因?yàn)?C/C++ 歷史包袱較多,不像 Java 的 Mavan, 更不像 Rust 的 Cargo + Crates。雖然有 vcpkg, conan 和 xmake 等, 但是公司自研的庫(kù)并不能很好的用這些工具管理起來(lái)
于是乎, 實(shí)際工作中不少人的工程里, 把若干個(gè) .a
文件放在 lib
目錄下,每個(gè)庫(kù)文件名字中并沒(méi)有包含版本號(hào)信息; 而項(xiàng)目的運(yùn)行結(jié)果不符合預(yù)期、展開(kāi)排查時(shí), 或者遞交版本時(shí), 需要清晰的列出這些依賴庫(kù)文件的版本信息。
使用 Python 的原因:跨平臺(tái), 開(kāi)發(fā)速度快。
2. 原理
查詢庫(kù)文件的版本號(hào),其實(shí)是另一個(gè)通用問(wèn)題的特定版本。
通用的問(wèn)題是:在一個(gè)二進(jìn)制文件中, 查找所有的字符串, 找出符合預(yù)設(shè)規(guī)則的那些字符串。
查詢版本號(hào),無(wú)非是對(duì)于公司的版本號(hào)有自己的規(guī)定, 可以從所有的字符串結(jié)果中進(jìn)行過(guò)濾。由于不同公司、不同項(xiàng)目可能有不同的版本號(hào)規(guī)則,我們重點(diǎn)關(guān)注兩點(diǎn):
- 怎樣從二進(jìn)制文件獲取字符串
- 怎樣從若干字符串中獲取想要的那個(gè)
Linux: strings 命令
在 Linux 下可以使用自帶的 strings 命令, 來(lái)列出一個(gè)二進(jìn)制文件中的所有字符串。以常用的 ls 命令為例,我們進(jìn)行查詢:
zz@Legion-R7000P% which strings /usr/bin/strings zz@Legion-R7000P% strings /bin/ls | more
Windows: strings 命令
Windows 并不默認(rèn)帶有 strings 命令, 不過(guò)微軟官方提供了一個(gè)版本:
https://docs.microsoft.com/zh-cn/sysinternals/downloads/strings
3. 基于 Python 實(shí)現(xiàn) strings 命令
對(duì)于 Windows 用戶, 如果安裝有 Python, 則可以基于 Python 實(shí)現(xiàn) strings 命令等同的函數(shù);由于 strings 的結(jié)果是非常多的字符串,往往還需要按版本號(hào)字符串特點(diǎn)進(jìn)行過(guò)濾(正則匹配),繼續(xù)使用 Python 的正則模塊進(jìn)行匹配是比較容易的。
def strings(fname): """ Remake `strings` command in Python This function behaves like `strings` command in linux/windows. If no desired result returned, you may just tweak the regular expression pattern. ref: https://gist.github.com/berdario/114b2daf9b43fe924676 Example: import arczip for word_bytes in arczip.strings(lib_pth): word = word_bytes.decode() if ('version' in word): print(word) """ from mmap import mmap, ACCESS_READ import re pattern = '([\w/.\s(:)-]{10,200})' with open(fname, 'rb') as f, mmap(f.fileno(), 0, access=ACCESS_READ) as m: for match in re.finditer(pattern.encode(), m): yield match.group(0)
代碼短小精悍,簡(jiǎn)單解釋下:
- 我們認(rèn)為“字符串”是可以用一個(gè)正則表達(dá)式表示的: 英文字母、空格、短橫杠
-
、點(diǎn).
、冒號(hào):
([\w/.\s(:)-]{10,200})'
- 我們認(rèn)為字符串的長(zhǎng)度至少為10, 至多為 200. 這個(gè)限制的目的是, 如果允許的字符串長(zhǎng)度太長(zhǎng), 搜索時(shí)間會(huì)變慢,太短則很多單個(gè)字符不符合預(yù)期結(jié)果
- 使用
yield
, 迭代方式返回結(jié)果 - 支持 Windows, 支持 Linux, 基于 Python3
4. 基于Python的版本號(hào)查找
調(diào)用剛剛實(shí)現(xiàn)的 strings()
函數(shù), 對(duì)得到的結(jié)果進(jìn)行正則匹配,例如需要以公司名字開(kāi)頭,并且版本號(hào)是4位數(shù)字、用.
分隔的,那么可以是這樣的實(shí)現(xiàn):
# 匹配版本號(hào) def containVersion(word): versionPattern = r"_\d{1,3}.\d{1,3}.\d{1,10}.\d{1,5}" match = re.search(versionPattern, word) if (match is not None): return True return False # 給定庫(kù)文件, 打印匹配到的版本號(hào) def print_module_version(lib_pth): for word_bytes in strings(lib_pth): word = word_bytes.decode() if (word.startswith('YourCompany') and containVersion(word)): print(word) elif (word.startswith('your_company') and containVersion(word)): print(word)
5. 最終調(diào)用:一句話使用
if __name__ == '__main__': print_module_version('D:/work/kaku-project/lib/windows-x64/libObjectDetection.lib') print_module_version('D:/work/kaku-project/lib/windows-x64/libObjectDetection.dll') print_module_version('D:/work/kaku-project/lib/linux-arm64/libObjectDetection.a')
到此這篇關(guān)于Python3: 掃描庫(kù)文件并獲取版本號(hào)信息的文章就介紹到這了,更多相關(guān)Python獲取版本號(hào)信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序前端如何調(diào)用python后端的模型詳解
近期需要開(kāi)發(fā)一個(gè)打分的微信小程序,涉及到與后臺(tái)服務(wù)器的數(shù)據(jù)交互,這篇文章主要給大家介紹了關(guān)于微信小程序前端如何調(diào)用python后端模型的相關(guān)資料,需要的朋友可以參考下2022-04-04Python mutiprocessing多線程池pool操作示例
這篇文章主要介紹了Python mutiprocessing多線程池pool操作,結(jié)合實(shí)例形式分析了Python多線程模塊multiprocessing進(jìn)程池相關(guān)操作技巧,需要的朋友可以參考下2019-01-01詳解Python如何實(shí)現(xiàn)批量為PDF添加水印
我們有時(shí)候需要把一些機(jī)密文件發(fā)給多個(gè)客戶,為了避免客戶泄露文件,會(huì)在機(jī)密文件中添加水印。本文將利用Python實(shí)現(xiàn)批量為PDF添加水印,需要的可以參考一下2022-05-05基于Python編寫一個(gè)簡(jiǎn)單的端口掃描器
端口掃描是非常實(shí)用的,不止用在信息安全方面,日常的運(yùn)維也用得到。本文將利用Python編寫一個(gè)簡(jiǎn)單的端口掃描器,需要的可以參考一下2022-04-04Python JWT認(rèn)證與pyjwt包詳細(xì)介紹
JWT的聲明一般被用來(lái)在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源,也增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息,該token也可直接被用于認(rèn)證,也可被加密,這篇文章主要介紹了Python JWT認(rèn)證與pyjwt包簡(jiǎn)介,需要的朋友可以參考下2023-05-05python之如何使用openpyxl設(shè)置單元格樣式
這篇文章主要介紹了python之如何使用openpyxl設(shè)置單元格樣式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Python Web開(kāi)發(fā)模板引擎優(yōu)缺點(diǎn)總結(jié)
這篇文章主要介紹了Python Web開(kāi)發(fā)模板引擎優(yōu)缺點(diǎn)總結(jié),需要的朋友可以參考下2014-05-05