Python3 扫描库文件并获取版本号信息的操作方法
作者:baiyu33 发布时间:2023-08-11 19:14:17
1. 目的
在 C/C++ 开发中使用了第三方库,具体说是 .a
, .lib
, .dll
等文件,想通过 Python 查询出这些文件中的版本号信息。
有人可能好奇,这里简单消除可能得疑虑:
为什么不用源代码,而用库?
因为库文件提供了良好的隔离性,避免了繁杂的编译选项指定, 避免了潜在的不小心改了代码导致的不一致
为什么不用包管理工具来设定和查询库文件的版本?
因为 C/C++ 历史包袱较多,不像 Java 的 Mavan, 更不像 Rust 的 Cargo + Crates。虽然有 vcpkg, conan 和 xmake 等, 但是公司自研的库并不能很好的用这些工具管理起来
于是乎, 实际工作中不少人的工程里, 把若干个 .a
文件放在 lib
目录下,每个库文件名字中并没有包含版本号信息; 而项目的运行结果不符合预期、展开排查时, 或者递交版本时, 需要清晰的列出这些依赖库文件的版本信息。
使用 Python 的原因:跨平台, 开发速度快。
2. 原理
查询库文件的版本号,其实是另一个通用问题的特定版本。
通用的问题是:在一个二进制文件中, 查找所有的字符串, 找出符合预设规则的那些字符串。
查询版本号,无非是对于公司的版本号有自己的规定, 可以从所有的字符串结果中进行过滤。由于不同公司、不同项目可能有不同的版本号规则,我们重点关注两点:
怎样从二进制文件获取字符串
怎样从若干字符串中获取想要的那个
Linux: strings 命令
在 Linux 下可以使用自带的 strings 命令, 来列出一个二进制文件中的所有字符串。以常用的 ls 命令为例,我们进行查询:
zz@Legion-R7000P% which strings
/usr/bin/strings
zz@Legion-R7000P% strings /bin/ls | more
Windows: strings 命令
Windows 并不默认带有 strings 命令, 不过微软官方提供了一个版本:
https://docs.microsoft.com/zh-cn/sysinternals/downloads/strings
3. 基于 Python 实现 strings 命令
对于 Windows 用户, 如果安装有 Python, 则可以基于 Python 实现 strings 命令等同的函数;由于 strings 的结果是非常多的字符串,往往还需要按版本号字符串特点进行过滤(正则匹配),继续使用 Python 的正则模块进行匹配是比较容易的。
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)
代码短小精悍,简单解释下:
我们认为“字符串”是可以用一个正则表达式表示的: 英文字母、空格、短横杠
-
、点.
、冒号:
([\w/.\s(:)-]{10,200})'
我们认为字符串的长度至少为10, 至多为 200. 这个限制的目的是, 如果允许的字符串长度太长, 搜索时间会变慢,太短则很多单个字符不符合预期结果
使用
yield
, 迭代方式返回结果支持 Windows, 支持 Linux, 基于 Python3
4. 基于Python的版本号查找
调用刚刚实现的 strings()
函数, 对得到的结果进行正则匹配,例如需要以公司名字开头,并且版本号是4位数字、用.
分隔的,那么可以是这样的实现:
# 匹配版本号
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
# 给定库文件, 打印匹配到的版本号
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. 最终调用:一句话使用
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')
来源:https://blog.csdn.net/baiyu33/article/details/130695056
猜你喜欢
- 1. 用 Numpy ndarray 作为数据传入 plyimport numpy as npimport matplotlib as mp
- 技术在进步,思维在发展,网页上的花样当然也要一天天地赶时髦了。在“滚动字符”、“跑马灯”已成平常的今天,网页上还能变出新花样吗?◆制作鼠标指
- 第一种:利用functools 工具处理import functoolsresult = (lambda k: functools.redu
- 构建网络ResNet由一系列堆叠的残差块组成,其主要作用是通过无限制地增加网络深度,从而使其更加强大。在建立ResNet模型之前,让我们先定
- 1.流程控制语 break用于结束整个循环结构,直接退出整个循环例:用两种循环模拟密码输入输入正确就退出循环,输入错误可以重新输入,有三次输
- 一、张量裁剪1.tf.maximum/minimum/clip_by_value()该方法按数值裁剪,传入tensor和阈值,maximum
- 1、 string的定义Golang中的string的定义在reflect包下的value.go中,定义如下:StringHeader 是字
- 前言通常都听到别人说,计算机很牛逼,很聪明,其实计算机一点都不聪明,光是你要跟他沟通,都会气 shi你,聪明的是在写程序的你。写程序就是跟计
- 导出到excel EXEC master..xp_cmdshell 'bcp Settle
- 1. 引言在本文中,我们将研究从列表中选择随机元素的不同实现方法。在日常项目中,我们经常会遇到这种情形,比如随机从多种数据增强策略中选择一种
- Bit-Packed Data TypesMySQL有一些存储类型使用一个值中的一些单个的比特位来紧凑的存储数据。纯技术上将,不管是底层的存
- 导语哈喽!大家好~我是木木子啦!自从写了一些表白类型的一些小脚本、小程序之后,越发不可收拾了,哈哈哈。常常会有小粉丝说:这......小程序
- 前言在SQL Server数据库中,有时候会建立一些Windows认证的账号(域账号),例如,我们公司习惯给开发人员和Support同事开通
- 扫雷是一款益智类小游戏,最早于 1992 年由微软在 Windows 上发行,游戏适合于全年龄段,规则简单,即在最短的时间内找出所有非雷格子
- 前言在本文中,我们将设计一个可以执行算术运算的解释器。我们不会重新造轮子。文章将使用由 David M. Beazley 开发的词法解析器
- Redisredis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串
- 1.背景看到这个标题你可能想一个分块能有什么难度?还值得细说吗,最近确实遇到一个有意思的分块函数,写法比较巧妙优雅,所以写一个分享。日前在做
- 写在前面最近有几个有趣的小想法想实践一下,希望使用低功耗、低成本的硬件跑一些持续性的独立的服务。最初的想法是入手一个树莓派得了,开发板尺寸小
- 事件是将JavaScript脚本与网页联系在一起的主要方式,是JavaScript中最重要的主题之一,深入理解事件的工作机制以及它们对性能的
- 如何选择速度最快的站点? <html><head><meta http-equiv=&qu