您的位置:首页 - 教程 - python - 正文
python内置模块(4)

  这一部分是python内置模块系列的最后一部分,介绍了一些小巧有用的内置模块。

目录:

1.random

2.shelve

3. getpass

4.zipfile

5.tarfile

6.bisect

7.fileinput

一、random

random模块是python提供的生成伪随机数模块,使用很简单,如下的三个方法都是生成1个随机数:

import random
 
print(random.random())
print(random.randint(1, 2))
print(random.randrange(1, 10))

还有一些方法比较有意思,比如seed和choice。

import random

alist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
t = random.choice(alist)
print(t)

运行结果:

程序会在alist里面随机选择一个数。

下面是生成一个包含大写字母A-Z和数字0-9的随机验证码的程序

import random

checkcode = ''
for i in range(4):
    current = random.randrange(0,4)
    if current != i:
        temp = chr(random.randint(65,90))
    else:
        temp = random.randint(0,9)
    checkcode += str(temp)
print(checkcode)

二、shelve

shelve模块是一个简单的k,v键值对,将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式。

它只有一个open和一个close方法,与python的内置文件处理方法很像。

import shelve
 
d = shelve.open('shelve_test') #打开一个文件
 
class Test(object):
    def __init__(self,n):
        self.n = n
 
 
t = Test(123) 
t2 = Test(123334)
 
name = ["alex","rain","test"]
d["test"] = name #持久化列表
d["t1"] = t      #持久化类
d["t2"] = t2
 
d.close()

唯一需要注意的是,通过open获得的内容读入内存后,所进行的修改在close之前不会保存到文件中,因此看下面的代码:

import shelve

s = shelve.open("testfile")
s["key"] = ['a', 'b', 'c']
print(s['key'])
s['key'].append('d')
print(s['key'])

运行结果:

['a', 'b', 'c']
['a', 'b', 'c']

“d”并没有被添加到列表的里面。怎么解决这个问题?使用一个临时变量!

import shelve

s = shelve.open("testfile")
s["key"] = ['a', 'b', 'c']
print(s["key"])
tmp = s["key"]
tmp.append('d')
s["key"] = tmp
print(s["key"])

运行结果:

['a', 'b', 'c']
['a', 'b', 'c', 'd']

三、getpass

  getpass模块非常简单,它能够让你在输入密码的时候不会在屏幕上显示密码,安全性更高。注意:在pycharm环境里这个模块用不了!

  getpass模块只有2个常用方法:getpass和getuser。参考下面的例子:

import getpass

pwd = getpass.getpass("请输入密码: ")  # 可代替input方法,接收用户输入的密码


print(getpass.getuser())  # getuser方法会返回当前执行程序的用户名

四、zipfile

  当你需要压缩文件的时候,使用这个模块会比较方便。

import zipfile

# 压缩
z = zipfile.ZipFile('laxi.zip', 'w')
z.write('a.log')        
z.write('data.data')             # 可以一个一个添加文件进压缩包
z.close()

# 解压
z = zipfile.ZipFile('laxi.zip', 'r')
z.extractall()                              # 这是一次性将压缩包内的文件全部解压出来 
z.close()    

  要单独解压压缩包内的某个文件就需要先获得压缩包内的文件名列表。zipfile提供了一个namelist方法。

import zipfile

z = zipfile.ZipFile('laxi.zip', 'r')
ret = z.namelist()
print(ret)
z.close()

运行结果:

['testfile.bak', 'testfile.dat']

  然后通过具体的文件名去解压某个文件。zipfile提供了extract方法。

import zipfile

z = zipfile.ZipFile('laxi.zip', 'r')
z.extract("testfile.bak")
z.close()

五、tarfile

  当你需要对文件进行打包的时候,这个模块比较方便。一般的用法如下:

import tarfile

# 压缩
tar = tarfile.open('your.tar','w')
tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log')
tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log')
tar.close()

# 解压
tar = tarfile.open('your.tar','r')
tar.extractall()  # 可设置解压地址
tar.close()

tarfile解压缩

注意和zipfile的区别,在实例对象的时候用的是open方法,而不是类似“zipfile”的方法。其它用法基本类似。

如果要解包单独的文件,请先用getmembers方法获取包内的文件名,然后使用extract方法解包指定的文件,类似上面的zipfile模块。

六、bisect

  这是一个python内置的二分查找法模块,其源码短得可怜。

"""Bisection algorithms."""

def insort_right(a, x, lo=0, hi=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.

    If x is already in a, insert it to the right of the rightmost x.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    a.insert(lo, x)

insort = insort_right   # backward compatibility

def bisect_right(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.

    The return value i is such that all e in a[:i] have e <= x, and all e in
    a[i:] have e > x.  So if x already appears in the list, a.insert(x) will
    insert just after the rightmost x already there.

    Optional args lo (default '
;%ވZh8HE'
;%ވZh bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]: hi = mid
        else: lo = mid+1
    return lo

bisect = bisect_right   # backward compatibility

def insort_left(a, x, lo=0, hi=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.

    If x is already in a, insert it to the left of the leftmost x.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if a[mid] < x: lo = mid+1
        else: hi = mid
    a.insert(lo, x)


def bisect_left(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.

    The return value i is such that all e in a[:i] have e < x, and all e in
    a[i:] have e >= x.  So if x already appears in the list, a.insert(x) will
    insert just before the leftmost x already there.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if a[mid] < x: lo = mid+1
        else: hi = mid
    return lo

# Overwrite above definitions with a fast C implementation
try:
    from _bisect import *
except ImportError:
    pass
bisect源码

  模块内只有4个方法:bisect_right、bisect_left、insort_right和insort_left。然后通过将bisect_right赋值给bisect,将insort_right赋值给insort实现向后兼容。实际使用中,是需要记住bisect和insort两个方法即可。

  bisect模块的使用方法通常是:bisect.bisect(list,x),其中x表示要查找的值,list是一个默认已经排好序的列表。

  bisect():返回值是x在列表中应处的位置下标,并不修改列表本身。

import bisect

x = 200
list1 = [1, 3, 6, 24, 55, 78, 454, 555, 1234, 6900]
ret = bisect.bisect(list1, x)
print("返回值: ", ret)
print("list1 = ", list1)

运行结果:

返回值:  6
list1 =  [1, 3, 6, 24, 55, 78, 454, 555, 1234, 6900]

  insort():返回值是将x插入到列表中后的新列表。x插在它的大小排序所在位置。

import bisect

x = 200
list1 = [1, 3, 6, 24, 55, 78, 454, 555, 1234, 6900]
ret = bisect.insort(list1, x)
print("返回值: ", ret)
print("list1 = ", list1)

运行结果:

返回值:  None
list1 =  [1, 3, 6, 24, 55, 78, 200, 454, 555, 1234, 6900]

七、fileinput

  使用过python内置的open方法处理文件的同学都知道,它没有直接修改文件内容的方法。这个fileinput可以帮助我们轻松的实现文件内容的修改功能。fileinput模块中的重要方法如下:

input([files[, inplace[, backup]])

  最重要的方法,用于遍历打开的文件,inplace为True的时候,会将修改写入文件,backup为True的时候会进行备份操作。

filename()

  返回当前文件的名字

lineno()

  返回当前(累计)的行数。同时处理多个文件时,行数会累计。

filelineno()

  返回当前文件的总行数。处理新文件时,行数会重置为1,重新计数。

isfirstline()

  检查当前行是否是文件的第一行

isstdin()

  检查最后一行是否来自sys.stdin

nextfile()

  关闭当前文件,移动到下一个文件(fileinput是可以同时处理多个文件的!)

close() 

  关闭整个文件链,结束迭代。

  为了演示fileinput的使用,假设编写了如下的一个脚本,想要为其代码进行编号。为了让脚本在进行代码编号后仍然能够正常运行,我们只能在每一行的右侧加上#来注释行号。其中,我们假定每个代码行最多有40个字符。具体代码如下:

import fileinput                        
                                        
f = fileinput.input(inplace=True)        
for line in f:                          
    line = line.rstrip()                    
    num = fileinput.lineno()             
    print("%-40s # %2i" % (line, num))      
f.close()

  注意,只能使用rstrip,不能直接用strip,那样会把左边的缩进也给去掉了。

请在终端环境下,使用python fileinput_test.py fileinput_test.py的方式执行程序,结果如下:

import fileinput                         #  1
                                         #  2
f = fileinput.input(inplace=True)        #  3
for line in f:                           #  4
    line = line.rstrip()                 #  5
    num = fileinput.lineno()             #  6
    print("%-40s # %2i" % (line, num))   #  7
f.close()                                #  8

要小心使用inplace参数,它会修改文件。应该在不适用inplace设置的情况下仔细测试自己的程序(这样只会打印出结果),在确保程序工作正常后再修改文件。  


评论: