Key*_*Usr 10 python hardware uuid mac-address identifier
我试图找到一些我可以用作我的脚本的唯一字符串/数字的东西,它固定在一台机器上并且很容易获得(跨平台).我认为一台机器会有一张网卡.我不需要它真正独特,但必要的是它应该长期固定,尽可能少.
我知道MAC可以更改,我可能会在我的脚本中发出警告,但我不希望每天早上都有人更改MAC.
我想出的是uuid.getnode(),但在文档中有:
如果所有获取硬件地址的尝试都失败,我们选择一个随机的48位数字
这是否意味着对于每个函数调用我得到另一个随机数,因此如果MAC无法获得则不可能使用它?
...在具有多个网络接口的计算机上,可以返回其中任何一个的MAC地址.
这句话是否意味着getnode()获得所有可用的随机(或第一)MAC?如果首次获得MAC A而下次获得MAC B怎么办?如果我得到一个固定的列表就没有问题(排序,连接,tadaaa!)
我问,因为我自己无法测试它.
我不建议使用 MAC 地址作为唯一的机器标识符,因为它可能会根据所使用的网络而变化。相反,我建议使用机器的本机 GUID,由操作系统在安装过程中分配。我编写了一个小型的跨平台 PyPI 包,用于查询计算机的本机 GUID,称为py-machineid。
本质上,它看起来像这样,但通过一些特定于 Windows 的 WMI 注册表查询来获得更准确的 ID。该软件包还支持对 ID 进行哈希处理,以使其匿名。
import subprocess
import sys
def run(cmd):
try:
return subprocess.run(cmd, shell=True, capture_output=True, check=True, encoding="utf-8") \
.stdout \
.strip()
except:
return None
def guid():
if sys.platform == 'darwin':
return run(
"ioreg -d2 -c IOPlatformExpertDevice | awk -F\\\" '/IOPlatformUUID/{print $(NF-1)}'",
)
if sys.platform == 'win32' or sys.platform == 'cygwin' or sys.platform == 'msys':
return run('wmic csproduct get uuid').split('\n')[2] \
.strip()
if sys.platform.startswith('linux'):
return run('cat /var/lib/dbus/machine-id') or \
run('cat /etc/machine-id')
if sys.platform.startswith('openbsd') or sys.platform.startswith('freebsd'):
return run('cat /etc/hostid') or \
run('kenv -q smbios.system.uuid')
Run Code Online (Sandbox Code Playgroud)
我设法在我的 android 设备上测试了第一部分,并在每次运行新的 python 时创建了随机数,因此它根本无法用于此目的。
第二个问题本身就被淹死了,因为如果在文档中它提到它可能会返回any one of them,那么它就不是你可以依赖的东西(+我找不到可以测试它的机器)。一个不错的包netifaces来拯救,它做了类似的事情
netifaces.interfaces() # returns e.g. ['lo', 'eth0', 'tun2']
netifaces.ifaddresses('eth0')[netifaces.AF_LINK]
# returns [{'addr': '08:00:27:50:f2:51', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]
Run Code Online (Sandbox Code Playgroud)
然而我宁愿放弃使用 MAC,我得到了一些更稳定的东西。
现在是标识符:
1) 窗户:
执行这个并获得输出可能就足够了:
wmic csproduct get UUID
Run Code Online (Sandbox Code Playgroud)
或者我使用过的并且在注册表 ( HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography) 中可用的:
import _winreg
registry = _winreg.HKEY_LOCAL_MACHINE
address = 'SOFTWARE\\Microsoft\\Cryptography'
keyargs = _winreg.KEY_READ | _winreg.KEY_WOW64_64KEY
key = _winreg.OpenKey(registry, address, 0, keyargs)
value = _winreg.QueryValueEx(key, 'MachineGuid')
_winreg.CloseKey(key)
unique = value[0]
Run Code Online (Sandbox Code Playgroud)
2)Linux:
/sys/class/dmi/id/board_serial
Run Code Online (Sandbox Code Playgroud)
或者
/sys/class/dmi/id/product_uuid
Run Code Online (Sandbox Code Playgroud)
或者如果不是root:
cat /var/lib/dbus/machine-id
Run Code Online (Sandbox Code Playgroud)
3)安卓:
如果你正在使用 python 并且不想弄乱 Java 的东西,那么这应该工作得很好:
import subprocess
cmd = ['getprop', 'ril.serialnumber']
self.unique = subprocess.check_output(cmd)[:-1]
Run Code Online (Sandbox Code Playgroud)
但是,如果您喜欢 Java,那么请选择这个答案,尽管 evenANDROID_ID的唯一性在允许更改的情况下相当值得商榷,因此序列号很可能是一个更安全的选择。
请注意,就像链接答案中已经提到的那样,甚至ril.serialnumber可以为空/空或不存在(缺少键)。即使使用官方的Android API也会发生同样的事情,其中明确说明了这一点:
硬件序列号(如果有)。
Mac/iPhone:
我找不到任何解决方案,因为我无法访问其中任何一个,但是如果有一个保存机器 ID 值的变量,那么您应该能够通过简单的方式到达那里subprocess.check_output()