纸上得来终觉浅,绝知此事要躬行。
实事求是,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:00 的UTC 计算起的秒数 |
%(relativeCreated)d |
日志被创建时间与日志模块被加载时间的时间差,单位为毫秒 |
%(asctime)s |
日志创建时间;默认格式2003-07-0816:49:45,896 ,逗号后为毫秒数 |
%(msecs)d |
毫秒级别的日志创建时间 |
%(thread)d |
线程 ID(如果可用) |
%(threadName)s |
线程名称(如果可用) |
%(process)d |
进程 ID(如果可用) |
%(message)s |
日志信息 |