玩转大数据

Python 开发过程中遇到的问题记录

2021-10-11  本文已影响0人  AlienPaul

写在前面

近期使用Python编写了一段项目维护脚本。期间遇到了不少问题,比如Python版本兼容问题,中文问题等。本篇将遇到的问题整理分享给大家,不定期更新中。

文件编码问题

如果在文件中出现了中文,我们必须要指定文件编码为UTF-8格式,否则执行时会出错。需要在文件头添加:

# -*- coding:utf-8 -*-

简化Python执行方式

一般来说,执行python程序的方式为

python xxx.py

这种是标准的运行Python程序命令。但是显得较为啰嗦。我们可以在py文件开头添加:

#!/usr/bin/python

然后给此文件赋予执行权限,然后就可以使用:

./xxx.py

方式执行这个Python脚本了。

获取用户输入不回显

输入不回显典型的使用场景为提示用户输入密码之时。如果我们使用Shell编程,可以使用read命令的-s参数:

read -s PASSWORD

该命令将用户接下来输入的内容保存到PASSWORD变量中,且用户输入时不回显。

在Python中我们可以使用getpass库来完成这项工作。该方式兼容Python2和3。

import getpass

password = getpass.getpass("Please enter your password: ")

获取是否以root用户执行

实践中我们会遇到需要检测当前执行Python脚本的用户这种场景。比如我们编写的安装脚本要求用root用户执行。在Python中可使用os.getuid()方法获取运行当前脚本的uid。root用户的uid为0,所以仅需对比获取到的uid是否为0,即可判断当前执行的用户是否为root用户。

import

def is_running_as_root():
    return os.getuid() == 0

Python import搜索路径

有时候我们在IDE编写好的脚本放到服务器上执行会提示import错误,要import的东西找不到。这时候我们需要配置Python的import搜索路径。

Python的import搜索路径保存在sys.path变量中,为数组类型。我们可以把它打印出来,查看当前的path配置。

import sys

print(sys.path)

修改sys.path的方法有两种。

  1. 使用sys.path.append(search_path)追加新的搜索路径到sys.path数组中。
  2. 配置PYTHONPATH环境变量。需要注意的是此方法仅在当前会话中生效。

Python 2和3的兼容问题

input和raw_input

在Python 3中只有input函数。作用为获取标准输入。例如我们编写:

username = input("Please input your name: ")

执行的时候会首先打印出Please input your name:提示语,然后将用户输入的字符串保存在username变量中。

但是在Python 2中,功能相同的函数却叫做raw_input,但是在Python 3中没有这个函数。input函数在Python 2中也有,但作用完全不同。Python 2的input函数会把用户的输入作为表达式去解析,如果用户的输入无法解析,会抛出SyntaxError

所以说获取用户输入,在Python 2中使用raw_input,在Python 3中则需要用input

另外,在Python 2和3中均可以使用如下方式读取用户输入:

import sys

username = sys.stdin.readline(10).strip()

print(username)

sys.stdin.readline()后面的参数为用户输入的长度限制,如果用户输入的长度超过限制,会被截断。

sys.stdin.readline()input以及raw_input最大的不同是sys.stdin.readline()会捕获到结尾的换行符\n。因此需要加一个strip,去掉用户输入末尾的换行符。

字典内容的排序问题

例如下面的一段程序:

if __name__ == '__main__':
    _dict = {
        "1": "一",
        "2": "二",
        "3": "三",
        "4": "四"
    }
    for k, v in _dict.items():
        print("key: {} | value: {}".format(k, v))

如果我们在Python 3.6及以上版本执行,每次的输出都是:

key: 1 | value: 一
key: 2 | value: 二
key: 3 | value: 三
key: 4 | value: 四

也就是说,在Python3.6及其以上的版本,字典内元素是有序的。

但是在Python3.6以下的版本,字典内元素的顺序是无法保证的。

为了解决这个问题,我们可以使用Python提供的collections.OrderedDict。使用方式如下所示:

import collections

_dict = collections.OrderedDict()
_dict['1'] = 'A'
_dict['2'] = 'B'
_dict['3'] = 'C'
_dict['4'] = 'D'

for k,v in _dict.items():
    print(k, v)

以上程序无论在Python 2还是3中运行多少次,输入的结果顺序都不会改变,OrderedDict是可以保证内部的元素顺序的。

获取Python版本的方法

import sys

version = sys.version_info
print(version)

执行后我们可以看到类似如下输出:

sys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)

到这里就很清晰了。比如我们要获取Python的主版本号,只需要获取sys.version_info.major变量的值即可。

获取Linux发行版

在Python 2中我们可借助于platform包,方式如下:

import platform

print(platform.dist())

输出是一个元组,比如:

('centos', '7.4.1708', 'Core')

但是在Python 3中执行上述脚本会报错:

AttributeError: module 'platform' has no attribute 'dist'

原因是Python 3种的platform没有dist这个属性。那么问题来了,在Python 3中我们该怎么办?

可以借助distro库。这个库是Python 3独有的,不能在Python 2中使用。

import distro

print(distro.linux_distribution())

问题似乎是解决了,但是这两种写法只能在对应的Python版本运行,无法兼容。为了解决这个问题,我们可以使用前面介绍的判断Python版本的方法,在不同版本调用不同的方法。如下所示:

import sys

def get_distribution():
    if sys.version_info.major == 2:
        import platform
        return platform.dist()
    else:
        import distro
        return distro.linux_distribution()

我们还可以判断platform这个包是否具有dist,来决定使用platform.dist()还是distro.linux_distribution()方式。

def get_distribution():
    import platform
    if hasattr(platform, "dist"):
        return platform.dist()
    else:
        import distro
        return distro.linux_distribution()
上一篇 下一篇

猜你喜欢

热点阅读