Python常见内建模块


纸上得来终觉浅,绝知此事要躬行。

Python常见内建模块


实事求是,Python 的强大之处在于它有非常丰富且强大的标准库和第三方库,几乎你想要实现的任何功能都有相应的 Python 库来提供支持,就类似于 JAVA 的 jar 包或前端中的 JS 库。

1. os

内建的os模块中主要包含了创建和管理进程或文件系统内容,比如操纵文件和目录的函数。而且os模块为平台特定的一些模块做了包装,这样在各个平台普遍适用。

  • 文件目录相关操作
In [1]: import os

In [2]: os.getcwd()
Out[2]: '/Users/escape'

In [3]: os.chdir('./Escape/MorePractise')

In [4]: os.getcwd()
Out[4]: '/Users/escape/Escape/MorePractise'

In [6]: os.getenv('SHELL')
Out[6]: '/bin/zsh'

In [7]: os.environ.get('SHELL')
Out[7]: '/bin/zsh'
In [8]: os.listdir('.')
Out[8]:
['magic.py',
 '__pycache__',
 'jumpserver_on_docker.sh',
 '.python-version',
 'update_chis.sh',
 'delete_server_log.py']

In [9]: os.walk('.')
Out[9]: <generator object walk at 0x10c8afa98>

In [10]: list(os.walk('.'))
Out[10]:
[('.',
  ['__pycache__'],
  ['magic.py',
   'jumpserver_on_docker.sh',
   '.python-version',
   'update_chis.sh',
   'delete_server_log.py']),
 ('./__pycache__', [], ['magic.cpython-36.pyc'])]

In [11]: os.mkdir('test')

In [12]: os.makedirs('test1/test2')

In [14]: os.rename('test', 'miss')

In [15]: os.rmdir('miss')
  • 获取进程信息的操作
In [21]: os.getgid()
Out[21]: 20

In [22]: os.geteuid()
Out[22]: 501

In [23]: os.getpid()
Out[23]: 60185

2. os.path

内建的os.path模块中主要包含了和路径相关的操作,这个模块非常非常常用。

  • 路径基本操作
In [1]: import os.path

In [2]: home = '/home/escape/a.txt'

In [3]: os.path.dirname(home)
Out[3]: '/home/escape'

In [4]: os.path.basename(home)
Out[4]: 'a.txt'

In [5]: os.path.exists(home)
Out[5]: False

In [6]: os.path.isdir(home)
Out[6]: False

In [7]: os.path.isfile(home)
Out[7]: False

In [8]: os.path.abspath(home)
Out[8]: '/home/escape/a.txt'
  • 路径高级操作
In [10]: os.path.join('/home', 'escape', 'index.html')
Out[10]: '/home/escape/index.html'

In [11]: os.path.split(home)
Out[11]: ('/home/escape', 'a.txt')

In [12]: os.path.splitext(home)
Out[12]: ('/home/escape/a', '.txt')

3. sys

内建的sys模块主要提供了特定系统的配置和操作,它和os模块是Python开发中经常会被使用到的两个模块,需要熟悉和掌握。

  • 系统信息查询
In [1]: import sys

# 用来构建解释器的操作系统平台
In [2]: sys.platform
Out[2]: 'darwin'

# 构建时的版本信息,包含完整的版本号和构建日期、编译器、平台信息等
In [3]: sys.version
Out[3]: '3.6.4 (default, Mar 29 2018, 00:58:49) \n[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)]'

# 同样是版本信息,但不是字符串,可以直接获得对应类型版本的信息
In [4]: sys.version_info
Out[4]: sys.version_info(major=3, minor=6, micro=4, releaselevel='final', serial=0)

# 搜索模块的路径列表
In [5]: sys.path[0]
Out[5]: ''

# 已经导入的模块列表
In [6]: sys.modules.get('xml')
Out[6]: <module 'xml' from '/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/xml/__init__.py'>
  • 引用计数和垃圾回收
# Python使用引用计数和垃圾回收来完成内存的管理
# 当一个对象的引用计数标记为零的时候,就会被解释器进行回收
# 我们看到对象的引用计数总是多一个,因为getrefcount也会消耗一个

In [7]: d = []

In [8]: sys.getrefcount(d)
Out[8]: 2

In [9]: x = d

In [10]: sys.getrefcount(d)
Out[10]: 3

In [11]: del x

In [12]: sys.getrefcount(d)
Out[12]: 2
In [13]: for obj in ([], {}, (), None, 'string', 123, ''):
    ...:     print(obj.__class__.__name__, sys.getsizeof(obj))
    ...:
list 64
dict 240
tuple 48
NoneType 16
str 55
int 28
str 49
  • 命令行参数
In [14]: a, b = 1, 2

In [15]: a, b, *c = range(3)

In [16]: a, b, c
Out[16]: (0, 1, [2])

In [17]: a, *b, c = range(3)

In [18]: a, b, c
Out[18]: (0, [1], 2)
import sys

script_name, *args = sys.argv
print(f'Script: {script_name}')
print(f'Arguments: {args}')

4. csv

逗号分隔值简称为csv模块,它是以纯文本的格式进行存储表格数据,且纯文本就表示字符序列并不是二进制格式的,很方便被读取和二次处理。

  • 写入和读取文本内容
In [1]: import csv

In [2]: with open('test.csv', 'wt') as f:
   ...:     writer = csv.writer(f)
   ...:     writer.writerow(('ID', 'NAME', 'TYPE'))
   ...:     for i in range(3):
   ...:         row = (i, f'user-{i}', f'type-{i}')
   ...:         writer.writerow(row)
   ...:

In [3]: cat test.csv
ID,NAME,TYPE
0,user-0,type-0
1,user-1,type-1
2,user-2,type-2

In [5]: with open('test.csv', 'rt') as f:
   ...:     reader = csv.reader(f)
   ...:     for line in reader:
   ...:         print(line)
   ...:
['ID', 'NAME', 'TYPE']
['0', 'user-0', 'type-0']
['1', 'user-1', 'type-1']
['2', 'user-2', 'type-2']
  • 读入为有序的字典
In [6]: with open('test.csv', 'rt') as f:
   ...:     reader = csv.DictReader(f)
   ...:     for line in reader:
   ...:         print(line)
   ...:
OrderedDict([('ID', '0'), ('NAME', 'user-0'), ('TYPE', 'type-0')])
OrderedDict([('ID', '1'), ('NAME', 'user-1'), ('TYPE', 'type-1')])
OrderedDict([('ID', '2'), ('NAME', 'user-2'), ('TYPE', 'type-2')])

5. datetime

内建的datetime模块主要提供了对于日期和时间的解析、格式化和时间运算的功能。

  • 时间的获取
In [1]: import datetime

In [2]: now = datetime.datetime.now()

In [3]: now
Out[3]: datetime.datetime(2018, 7, 12, 14, 53, 14, 735444)

In [4]: now.month, now.day, now.second
Out[4]: (7, 12, 14)

In [5]: today = datetime.date.today()

In [6]: today
Out[6]: datetime.date(2018, 7, 12)

In [7]: today.year, today.month, today.day
Out[7]: (2018, 7, 12)

In [9]: time1 = datetime.date(2018, 7, 12)

In [10]: time1 = datetime.date(2018, 7, 12, 0, 0)
  • 时间的偏移
In [14]: print('seconds  :', datetime.timedelta(seconds=1))
    ...: print('minutes   :', datetime.timedelta(minutes=1))
    ...: print('hours     :', datetime.timedelta(hours=1))
    ...: print('days      :', datetime.timedelta(days=1))
    ...: print('weeks     :', datetime.timedelta(weeks=1))
    ...:
seconds     : 0:00:01
minutes     : 0:01:00
hours       : 1:00:00
days        : 1 day, 0:00:00
weeks       : 7 days, 0:00:00
seconds     : 0:00:01

In [15]: hour = datetime.timedelta(hours=1)

In [16]: hour.total_seconds
Out[16]: <function timedelta.total_seconds>

In [17]: hour.total_seconds()
Out[17]: 3600.0

In [18]: today = datetime.date(2018, 7, 12)

In [19]: today + datetime.timedelta(days=1)
Out[19]: datetime.date(2018, 7, 13)

In [20]: today - datetime.timedelta(days=1)
Out[20]: datetime.date(2018, 7, 11)
  • 时间格式化
In [22]: dt_format = '%Y-%m-%d %H:%M:%S'

In [23]: now = datetime.datetime.now()

In [24]: print_format = now.strftime(dt_format)

In [25]: print(print_format)
2018-07-12 15:02:30

In [26]: date_time = datetime.datetime.strptime(print_format, dt_format)

In [27]: print(date_time)
2018-07-12 15:02:30

In [28]: date_time
Out[28]: datetime.datetime(2018, 7, 12, 15, 2, 30)

6. random

内建的random模块用于快速的生成伪随机数的,计算方法比较简单。伪随机过程好像是随机的,但其实并不是随机的。我们可以通过获取一定长度的伪随机序列,来推出seed的值,然后就可以推出下一个数的值。

  • 生成伪随机数
In [1]: import random

In [2]: for i in range(5):
   ...:     print(f'{random.random():.4f}', end='\t')
   ...:
0.9813    0.1015    0.0109    0.6008    0.2129

In [3]: for i in range(5):
   ...:     print(f'{random.uniform(10, 20):.4f}', end='\t')
   ...:
10.4435    18.8349    18.3479    17.2886    15.7793

In [4]: for i in range(5):
   ...:     print(f'{random.randint(1, 100)}', end='\t')
   ...:
31    40    16    98    86

In [5]: for i in range(5):
   ...:     print(f'{random.randint(1, 100, 5)}', end='\t')
   ...:
In [9]: for i in range(5):
   ...:     print(f'{random.randrange(1, 100, 5)}', end='\t')
   ...:
21    66    61    21    76
In [10]: random.sample(range(10), 3)
Out[10]: [6, 3, 1]

In [11]: random.choices(range(10), k=5)
Out[11]: [7, 9, 7, 0, 7]

In [12]: random.choice(['a', 'b', 'c'])
Out[12]: 'b'
  • 伪随机数定值
In [13]: import time

In [14]: t = time.time()

In [15]: random.seed(t)

In [16]: for i in range(5):
    ...:     print(f'{random.uniform(1, 10):.4f}', end='\t')
    ...:
3.4593    8.2056    4.8069    4.9577    5.6014

In [18]: random.seed(t)

In [19]: for i in range(5):
    ...:     print(f'{random.uniform(1, 10):.4f}', end='\t')
    ...:
3.4593    8.2056    4.8069    4.9577    5.6014

7. http.server

内建的http.server模块更够帮助我们快速的建立起一个Web服务。

# 在Python3的用法

# 浏览器访问 http://localhost:8000/
$ python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

# 浏览器访问 http://localhost:9090/❯
$ python -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
# 在Python2的用法
$ python -m SimpleHTTPServer
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
# 但是其不能添加登录认证密码,有些不安全
# 所以可以是用下面这个第三方库来替代,虽然现在已经不再更新了
https://github.com/sc0tfree/updog

# 安装第三方库
$ pip3 install updog

# 启动服务
$ updog -p 9000 --password 123456
$ updog -p 9000 --password 123456 -d /data/app/logs
$ updog -p 9000 --password 123456 -d /data/app/logs --ssl

8. logging

内建的logging模块主要是提供程序的日志打印,可以用于程序的调试以及问题的排查用的,分为终端打印以及保存到日志文件两种方式。

  • 日志级别变量的值
日志级别变量 对应的数值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0
  • 终端打印日志记录的方式
In [1]: import logging

In [2]: logging.warning('nginx is reload.')
WARNING:root:nginx is reload.

In [3]: logging.debug('nginx is runing...')
# 定义日志打印的默认运行级别
In [4]: logging.basicConfig(level=logging.WARNING)

# 固定的项目会有自己的logger日志实例
In [5]: logger1 = logging.getLogger('package1.module1')
In [6]: logger2 = logging.getLogger('package2.module2')

In [7]: logger1.warning('This message from module1')
WARNING:package1.module1:This message from module1

In [8]: logger2.warning('This message from module2')
WARNING:package2.module2:This message from module2

# 低于这个运行级别的信息将不会被打印
In [9]: logger2.debug('This message won"t be printed')
  • 日志记录报错到文件的方式
# 打印日志都有哪些处理器,root为默认logger,即日志实例
# 否则,都应该使用logging.getLogger的方式获取logger实例

import logging

logging.basicConfig(filename='app.log', level=logging.INFO)
logging.info('Started')
print(logging.root.handlers)
$ python loging_to_file.py
[<FileHandler /Users/escape/Escape/app.log (NOTSET)>]

$ cat myapp.log
INFO:root:Started
# 同样的代码,在IPython中运行会有一些问题,文件并不存在
# 问题原因是其交互式环境提供的Handler是StreamHandler,并非FileHandler

In [10]: logging.basicConfig(filename='myapp2.log', level=logging.INFO)

In : logging.info('Started')

In : cat app2.log
cat: myapp2.log: No such file or directory

In : logging.root.handlers
Out: [<StreamHandler <stderr> (NOTSET)>]

# 设置日志运行级别
In : logging.root.setLevel(logging.INFO)

In : logging.info('Started')
INFO:root:Started

In : cat app2.log
Started

In : logging.root.handlers
[<FileHandler /Users/escape/Escape/app2.log (NOTSET)>]
  • 最佳使用的方案
import logging

logger = logging.getLogger('xxx')
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

logger.debug('This is a %s', 'test')
  • 内置日志格式
内置日志格式 对应变量的含义
%(name)s 生成日志的 Logger 名称
%(levelno)s 数字形式的日志级别,包括六个级别
%(levelname)s 文本形式的日志级别,包括六个级别
%(pathname)s 输出该日志的语句所在源文件的完整路径(如果可用)
%(filename)s 文件名
%(module)s 输出该日志的语句所在的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行(如果可用)
%(created)f 日志被创建的时间,表示从1970-1-100:00:00UTC计算起的秒数
%(relativeCreated)d 日志被创建时间与日志模块被加载时间的时间差,单位为毫秒
%(asctime)s 日志创建时间;默认格式2003-07-0816:49:45,896,逗号后为毫秒数
%(msecs)d 毫秒级别的日志创建时间
%(thread)d 线程 ID(如果可用)
%(threadName)s 线程名称(如果可用)
%(process)d 进程 ID(如果可用)
%(message)s 日志信息

文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录