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 ...
随机推荐
- C++的封装性
C++的封装性 C++的阶段,我想根据C++的一些特有的特性分别写一些专题,每个专题我都捎带讲一些语法,当然不会很多,我还是会像C语言那样,内存结构贯穿始终,有汇编就有真相…… 本专题,我们讲述封装性 ...
- OI队内测试一【数论概率期望】
版权声明:未经本人允许,擅自转载,一旦发现将严肃处理,情节严重者,将追究法律责任! 序:代码部分待更[因为在家写博客,代码保存在机房] 测试分数:110 本应分数:160 改完分数:200 T1: 题 ...
- eclipse-ee修改字体大小和配置Tomcat服务器
参考博客:http://blog.csdn.net/lpftobetheone/article/details/17783791 一.EclipseEE背景色和字体的修改 1.Eclipse背景颜色修 ...
- robotium从入门到放弃 四 Robotium常用API
获取控件 getText() getEditText() getButton() getImage() getImageButton() getEditText() getView() getWe ...
- Selenium2(java)selenium常用API 四
WebElement相关方法 1.点击操作 WebElement button = driver.findElement(By.id("login")); button.click ...
- InnoDB的表类型,逻辑存储结构,物理存储结构
表类型 对比Oracle支持的各种表类型,InnoDB存储引擎表更像是Oracle中的索引组织表(index organized table).在InnoDB存储引擎表中,每张表都有个主键,如果在创建 ...
- 第四组UI组件:AdapterView及子类
AdapterView组件是一组重要的组件,AdapterView本省是一个抽象基类,它派生的子类在用法上十分相似,只是显示界面与一定的区别,因此这次针对它们的共性集中讲解,并突出介绍他们的区别. A ...
- Flex中操作XML的E4X方法
用于处理 XML 的 E4X 方法 Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本 ECMAScript for XML 规范定义了一组用于使用 XML 数据的类 ...
- 如何在NodeJS项目中优雅的使用ES6
如何在NodeJS项目中优雅的使用ES6 NodeJs最近的版本都开始支持ES6(ES2015)的新特性了,设置已经支持了async/await这样的更高级的特性.只是在使用的时候需要在node后面加 ...
- Hadoop权威指南: 专有数据类型
Writable 和 WritableComparable接口 Writable接口 ** Writable接口的主要目的是,当数据在网络上传输或从硬盘读写时,提供数据的序列化和反序列化机智 ** * ...