Python之路--你不知道的platform
某次在查看测试机(Ubuntu)发行版本时,发现得到的结果并不准确;本应得到Ubuntu,结果显示的却是Debian,大致代码如下
...
distribution_name = ['centos', 'ubuntu', 'redhat', 'debian', 'fedora']
class_name = {'centos': 'CentOS',
'ubuntu': 'Ubuntu',
'redhat': 'RedHat',
'debian': 'Debian',
'fedora': 'Fedora'}
...
for name in distribution_name:
if name in platform.platform.lower():
_platform = class_name[name]
break
...
项目使用的是可移植版的python,第一反应是用交互模式验证一下。
>>> import platform
>>> platform.platform()
'Linux-4.4.0-62-generic-x86_64-with-debian-stretch-sid'
得出的结果确实为debian。既没有报错,也没有异常,那么问题是出在哪里了呢?
遂又使用系统自带的python验证。
>>> import platform
>>> platform.platform()
'Linux-4.4.0-62-generic-x86_64-with-Ubuntu-16.04-xenial'
然而系统得到的却是正确的结果,难道是移植版本的bug?
在同事的提醒下,意识到应该看一下platform模块的源码,看看问题是否出在这里。
首先,查看platform模块中的platform方法
def platform(aliased=0, terse=0):
result = _platform)_cache.get((aliased, terse), None)
if result is not None:
return resut
system, node, release, version, machine, processor = uname()
...
elif system in ('Linux', ):
disname, distversion, distid = dist('')
...
def uname():
...
try:
system, node, release, version, machine = os.uname()
...
def dist(distname='', version='', id='',
supported_dists=_supported_dists):
return linux_distribution(distname, version, id,
supported_dists=supported_dists,
full_distribution_name=0)
当调用platform方法时,首先它回去模块缓存信息中查找,若有则直接返回。因为是第一次调用,缓存中肯定不会存有相应信息,这里可以跳过。
接着,通过uname方法获取system, node, release等信息,而uname方法主要是调用os.uname()获得相应信息。
>>> import os
>>> os.uname()
('Linux', 'uyun-VirtualBox', '4.4.0-62-generic', '#83-Ubuntu SMP Wed Jan 18 14:10:15 UTC 2017', 'x86_64')
尝试使用os.uname()后,除了能得到系统版本外发现并没有期望得到的相应发行版信息,跳过。
然后则是dist()方法。发现dist()方法实际上调用的python_implementation()。最终确定,获取系统版本的关键就在python_implementation()方法中。
以下为比较可移植版的python和Ubuntu自带的python源码(具体行号可能存在些许偏差)
...
259 _supported_dists = (
260 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
261 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
262 'UnitedLinux', 'turbolinux')
...
...
291 def linux_distribution(distname='', version='', id='',
292 supported_dists=_supported_dists,
293 full_distribution_name=1):
...
315 try:
316 etc = os.listdir('/etc')
317 except os.error:
318 # Probably not a Unix system
319 return distname, version, id
...
...
以上为移植版python的platform模块源码。
···
261 _supported_dists = (
262 'SuSE', 'debian', 'fedora', 'redhat', 'centos',
263 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
264 'UnitedLinux', 'turbolinux', 'Ubuntu')
...
293 _distributor_id_file_re = re.compile("(?:DISTRIB_ID\s*=)\s*(.*)", re.I)
294 _release_file_re = re.compile("(?:DISTRIB_RELEASE\s*=)\s*(.*)", re.I)
295 _codename_file_re = re.compile("(?:DISTRIB_CODENAME\s*=)\s*(.*)", re.I)
296
297 def linux_distribution(distname='', version='', id='',
298 supported_dists=_supported_dists,
299 full_distribution_name=1):
...
321 # check for the LSB /etc/lsb-release file first, needed so
322 # that the distribution doesn't get identified as Debian.
323 try:
324 with open("/etc/lsb-release", "rU") as etclsbrel:
325 for line in etclsbrel:
326 m = _distributor_id_file_re.search(line)
327 if m:
328 _u_distname = m.group(1).strip()
329 m = _release_file_re.search(line)
330 if m:
331 _u_version = m.group(1).strip()
332 m = _codename_file_re.search(line)
333 if m:
334 _u_id = m.group(1).strip()
335 if _u_distname and _u_version:
336 return (_u_distname, _u_version, _u_id)
337 except (EnvironmentError, UnboundLocalError):
338 pass
339
340 try:
341 etc = os.listdir('/etc')
342 except os.error:
343 # Probably not a Unix system
344 return distname,version,id
...
...
以上为Ubuntu系统自带python的platform模块源码。
首先可以看到,Ubuntu版本中platform的_supported_dists 元组中多了一个Ubuntu元素,并且在linux_destribution方法中,首先会尝试读取/etc/lsb-release文件;接着通过正则匹配(_distributor_id_file_re, _release_file_re, _codename_file_re),查找相应的值,如果都有结果,则直接返回。
读取/etc/lsb-release,发现里面存了一些Ubuntu系统版本信息。
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04 LTS"
那么显然,三个正则都将匹配到对应的值,返回(Ubuntu, 16.04, xenial)。
最终,正确的获取到Ubuntu发行版本。
Python之路--你不知道的platform的更多相关文章
- Python之路,Day17 - 分分钟做个BBS论坛
Python之路,Day17 - 分分钟做个BBS论坛 本节内容: 项目:开发一个简单的BBS论坛 需求: 整体参考"抽屉新热榜" + "虎嗅网" 实现不同 ...
- Python之路,Day8 - Socket编程进阶
Python之路,Day8 - Socket编程进阶 本节内容: Socket语法及相关 SocketServer实现多并发 Socket语法及相关 socket概念 socket本质上就是在2台 ...
- Python之路【第一篇】python基础
一.python开发 1.开发: 1)高级语言:python .Java .PHP. C# Go ruby c++ ===>字节码 2)低级语言:c .汇编 2.语言之间的对比: 1)py ...
- Python之路
Python学习之路 第一天 Python之路,Day1 - Python基础1介绍.基本语法.流程控制 第一天作业第二天 Python之路,Day2 - Pytho ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
- Python之路【第十九篇】:爬虫
Python之路[第十九篇]:爬虫 网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用 ...
- Python之路【第十八篇】:Web框架们
Python之路[第十八篇]:Web框架们 Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Pytho ...
- Python之路【第十七篇】:Django【进阶篇 】
Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接 ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
随机推荐
- Yii实现Password Repeat Validate Rule
在使用Yii时遇到这样的需求:在一个注册的页面输入两次密码,并验证两次输入是否一致.可是password的repeat的字段在数据库 并不存在.问题来了,如何创建一个password_repeat的属 ...
- asp.net 二级域名session共享
1.自定义类 namespace SessionShare{ public class CrossDomainCookie : IHttpModule { private string m_RootD ...
- p1349星屑幻想
这道题的原题目我也不知道是什么. 大致题意是有一个图,有些点的权值已确定,要求你确定其他点的权值使所有边两个点的权值的xor和最小,输出所有点的最终权值,输出有spj: 解法是最小割,由于题目要求的使 ...
- Nginx 限流
原文链接:http://colobu.com/2015/10/26/nginx-limit-modules/?utm_source=tuicool&utm_medium=referral 电商 ...
- Java经典案例之-判断兔子的数量(斐波那契数列)
/** * 描述:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子, * 假如兔子都不死,问每个兔子总数为多少? * 分析:根据题目条件可以推断 * 兔子的规律 ...
- eclipse开发velocity实例(初学)
开发环境 Eclipse Java EE IDE for Web Developers.(Version: Helios Service Release 1) jdk1.6.0_07 ...
- 搭建Minisipserve服务器实现局域网内IOS客户端idoubs的通信
idoubs是IOS设备开发的第一款全功能并开放源码的3GPP IMS客户端,它同时专为IOS平台开发设计的voIP测试版客户端,以doubango为框架,能实现当前最先进的多媒体功能,主要功能有:语 ...
- 从新手到高手c++全方位学习 pdf + 视频教程 共18章
淘宝已经和谐了这个网站,原网址:https://item.taobao.com/item.htm?spm=a1z09.8149145.0.0.mb00D0&id=17350311256& ...
- 如何一步一步用DDD设计一个电商网站(十二)—— 提交并生成订单
阅读目录 前言 解决数据一致性的方案 回到DDD 设计 实现 结语 一.前言 之前的十一篇把用户购买商品并提交订单整个流程上的中间环节都过了一遍.现在来到了这最后一个环节,提交订单.单从业务上看,这个 ...
- 《JAVASCRIPT高级程序设计》window/location/navigator/screen/history对象
如果要在web中使用JAVASCRIPT,那么BOM(浏览器对象模型)毫无疑问是最重要的部分.BOM提供了很多对象,例如,window.location.navigator.screen.histor ...