python3内置模块有哪些

sys模块

Python的sys模块提供访问由解释器使用或维护的变量的接口,并提供了一些函数用来和解释器进行交互,操控Python的运行时环境。

1)sys.argv

传递给程序的命令行参数列表;其中,sys.argv[0]表示脚本名称,各个参数均为字符串类型。

2)sys.exit(n)

程序退出,如果是正常退出是sys.exit(0),这里的参数可以自己填

3)sys.modules.keys()

返回所有已经导入的模块列表

4)sys.version

获取Python解释程序的版本信息

5)sys.platform

返回操作系统平台名称

6)sys.stdout

标准输出

7)sys.stdin

标准输入

8)sys.stderr

错误输出

time模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import time  # 引入time模块

# 获取当前时间戳 (1970纪元后经过的浮点秒数)。
ticks = time.time()
print("当前时间戳为:", ticks)  # 输出:1662628591.4172864

# 获取当前时间
localtime = time.localtime()
localtime = time.localtime(time.time())
print("本地时间为 :", localtime)
print("年:", localtime.tm_year)  # 四位年份
print("月:", localtime.tm_mon)  # 1~12
print("天:", localtime.tm_mday)  # 1~31
print("时:", localtime.tm_hour)  # 0~23
print("分:", localtime.tm_min)  # 0~59
print("秒:", localtime.tm_sec)  # 0 到 61 (60或61 是闰秒)
print("星期:", localtime.tm_wday)  # 0 到 6 (0是周一)
print("一年中第几天:", localtime.tm_yday)  # 一年中的第几天,1 到 366
print("是否为夏令时:", localtime.tm_isdst)  # 是否为夏令时,值有:1(夏令时)、0(不是夏令时)、-1(未知),默认 -1

# 格式化时间
# 接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。
# time.strftime(fmt[,tupletime])

# 格式化成2016-03-20 11:45:39形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

# 格式化成Sat Mar 28 22:24:24 2016形式
print(time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()))

# 将格式字符串转换为时间戳
a = "Sat Mar 28 22:24:24 2016"
print(time.mktime(time.strptime(a, "%a %b %d %H:%M:%S %Y")))

# %W 一年中的星期数(00-53)星期一为星期的开始
# 输出 2022-09-08 一年中第36周
print(time.strftime("%Y-%m-%d 一年中第%W周", time.localtime()))

# %U 一年中的星期数(00-53)星期天为星期的开始
# 输出 2022-09-08 一年中第36周
print(time.strftime("%Y-%m-%d 一年中第%U周", time.localtime()))

# %w 星期(0-6),星期天为星期的开始
# 输出 2022-09-08 星期4
print(time.strftime("%Y-%m-%d 星期%w", time.localtime()))

# %j 年内的一天(001-366)
# 输出 2022-09-08 一年中第251天
print(time.strftime("%Y-%m-%d 一年中第%j天", time.localtime()))

# %y 两位数的年份表示(00-99)
# 格式化成2022-09-08 17:47:12形式
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))

# %I 12小时制小时数(01-12)
# 格式化成2022-09-08 05:48:58形式
print(time.strftime("%Y-%m-%d %I:%M:%S", time.localtime()))

# %a 本地简化星期名称
# 输出 2022-09-08 Thu
print(time.strftime("%y-%m-%d %a", time.localtime()))

# %A 本地完整星期名称
# 输出 2022-09-08 Thursday
print(time.strftime("%Y-%m-%d %A", time.localtime()))

# %b 本地简化的月份名称
# 输出 2022-09-08 Sep
print(time.strftime("%Y-%m-%d %b", time.localtime()))

# %B 本地完整的月份名称
# 输出 2022-09-08 September
print(time.strftime("%Y-%m-%d %B", time.localtime()))

# %c 本地相应的日期表示和时间表示
# 输出 2022-09-08 Thu Sep  8 17:55:00 2022
print(time.strftime("%Y-%m-%d %c", time.localtime()))

# %x 本地相应的日期表示
# 输出 2022-09-08 09/08/22
print(time.strftime("%Y-%m-%d %x", time.localtime()))

# %X 本地相应的时间表示
# 输出 2022-09-08 18:30:01
print(time.strftime("%Y-%m-%d %X", time.localtime()))

# %Z 当前时区的名称
# 输出 2022-09-08 中国标准时间
print(time.strftime("%Y-%m-%d %Z", time.localtime()))

# 返回计时器的精准时间(系统的运行时间),包含整个系统的睡眠时间。由于返回值的基准点是未定义的,所以,只有连续调用的结果之间的差才是有效的。
print("返回系统运行时间:", time.perf_counter())
# 返回当前进程执行 CPU 的时间总和,不包含睡眠时间。由于返回值的基准点是未定义的,所以,只有连续调用的结果之间的差才是有效的。
print("返回进程运行时间", time.process_time())

# 接收时间戳(1970纪元后经过的浮点秒数)并返回格林威治天文时间下的时间元组t。注:t.tm_isdst始终为0
# 输出 time.struct_time(tm_year=2016, tm_mon=2, tm_mday=15, tm_hour=3, tm_min=56, tm_sec=49, tm_wday=0, tm_yday=46,  tm_isdst=0
print ("gmtime :", time.gmtime(1455508609.34375))

# 推迟调用线程的运行,secs指秒数。
time.sleep(1)

# time.timezone是当地时区(未启动夏令时)距离格林威治的偏移秒数(>0,美洲;<=0大部分欧洲,亚洲,非洲)。
print("time.timezone:", time.timezone)

datetime模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
datetime模块中常用的类是:
    date类
    time类
    datetime类
    timedelta类
"""
import datetime
from datetime import date
from datetime import time
from datetime import timedelta
# 如果单独引入了datetime类, 则不能再使用类似datetime.datetime.now()的的做法,直接使用datetime.now()即可,date和time类也是,否则就都得添加
from datetime import datetime

# ---------------------------------------- date类
# 获取当前日期
# 输出 2022-09-09
print("获取当前日期:", date.today())

# 表示日期的Date对象
# 输出 2019-04-13
print("表示日期的Date对象:", date(2019, 4, 13))

# 将时间戳转换为日期
# 输出 2019-12-13
print("将时间戳转换为日期:", date.fromtimestamp(1576244364))

# 今天的日期对象
today = date.today()
print("当前年:", today.year)
print("当前月:", today.month)
print("当前日:", today.day)

# ---------------------------------------- time类
# 表示时间的时间对象
# time(hour = 0, minute = 0, second = 0)
a = time()
print("a =", a)

# time(hour, minute and second)
b = time(11, 34, 56)
print("b =", b)

# time(hour, minute and second)
c = time(hour=11, minute=34, second=56)
print("c =", c)

# time(hour, minute, second, microsecond)
d = time(11, 34, 56, 234566)
print("d =", d)

# 打印时,分,秒和微秒
a = time(11, 34, 56)
print("小时=", a.hour)
print("分钟=", a.minute)
print("秒=", a.second)
print("微秒=", a.microsecond)

# ---------------------------------------- datetime类
# 获取当前日期和时间
# 输出 2022-09-09 08:52:28.199061
print("获取当前时间:", datetime.now())

# datetime(year, month, day)
# 输出 2019-11-28 00:00:00
a = datetime(2019, 11, 28)
print(a)

# datetime(year, month, day, hour, minute, second, microsecond)
# 输出 2019-11-28 23:55:59.342380
b = datetime(2019, 11, 28, 23, 55, 59, 342380)
print(b)

# 打印年,月,时,分和时间戳
a = datetime(2019, 12, 28, 23, 55, 59, 342380)
print("年 =", a.year)
print("月 =", a.month)
print("日 =", a.day)
print("时 =", a.hour)
print("份 =", a.minute)
print("时间戳 =", a.timestamp())

# 两个日期和时间之间的时差
t1 = date(year=2018, month=7, day=12)
t2 = date(year=2017, month=12, day=23)
t3 = t1 - t2
# 输出 201 days, 0:00:00
print("t3 =", t3)

t4 = datetime(year=2018, month=7, day=12, hour=7, minute=9, second=33)
t5 = datetime(year=2019, month=6, day=10, hour=5, minute=55, second=13)
t6 = t4 - t5
# 输出 -333 days, 1:14:20
print("t6 =", t6)
# 输出 <class 'datetime.timedelta'>
print("type of t3 =", type(t3))
print("type of t6 =", type(t6))

# 两个timedelta对象之间的时间差
t1 = timedelta(weeks=2, days=5, hours=1, seconds=33)
t2 = timedelta(days=4, hours=11, minutes=4, seconds=54)
t3 = t1 - t2
# 输出 14 days, 13:55:39
print("t3 =", t3)

# 打印负timedelta对象
t1 = timedelta(seconds=33)
t2 = timedelta(seconds=54)
t3 = t1 - t2
# 输出 -1 day, 23:59:39
print("t3 =", t3)
# 输出 0:00:21
print("t3 =", abs(t3))

# 持续时间(以秒为单位)
t = timedelta(days=5, hours=1, seconds=33, microseconds=233423)
print("total seconds =", t.total_seconds())

# 格式化时间
# current date and time
now = datetime.now()

t = now.strftime("%H:%M:%S")
print("time:", t)

s1 = now.strftime("%m/%d/%Y, %H:%M:%S")
# mm/dd/YY H:M:S format
print("s1:", s1)

s2 = now.strftime("%d/%m/%Y, %H:%M:%S")
# dd/mm/YY H:M:S format
print("s2:", s2)

# 从一个给定的字符串(表示日期和时间)创建一个datetime对象
date_string = "21 June, 2018"
print("date_string =", date_string)

date_object = datetime.strptime(date_string, "%d %B, %Y")
# 输出 2018-06-21 00:00:00
print("date_object =", date_object)

# 注意:如果需要根据其时区显示日期和时间。我们建议您使用第三方的pytZ模块,而不是自己处理时区

calendar模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
与日历相关
星期一是默认的每周第一天,星期天是默认的最后一天。更改设置需调用calendar.setfirstweekday()函数。
"""
import calendar

# 返回一个多行字符串格式的 year 年年历,3 个月一行,间隔距离为 c。 每日宽度间隔为w字符。每行长度为 21* W+18+2* C。l 是每星期行数。
cal = calendar.calendar(2016, w=2, l=1, c=6)
print(cal)

# 返回一个多行字符串格式的year年month月日历,两行标题,一周一行。每日宽度间隔为w字符。每行的长度为7* w+6。l是每星期的行数。
cal = calendar.month(2016, 1)
print("以下输出2016年1月份的日历:")
print(cal)
calendar.month(2016, 1, w=2, l=1)
print("以下输出2016年1月份的日历:")
print(cal)

# 返回当前每周起始日期的设置。默认情况下,首次载入 calendar 模块时返回 0,即星期一。
print("calendar.firstweekday():", calendar.firstweekday())

# 是闰年返回 True,否则为 False。
print("calendar.isleap(year):", calendar.isleap(2000))

# 返回在Y1,Y2两年之间的闰年总数。
print("calendar.leapdays(y1,y2):", calendar.leapdays(1900, 2000))

# 返回一个整数的单层嵌套列表。每个子列表装载代表一个星期的整数。Year年month月外的日期都设为0;范围内的日子都由该月第几日表示,从1开始。
print("calendar.monthcalendar(year,month):", calendar.monthcalendar(2016, 1))

# 返回两个整数。第一个是该月的星期几,第二个是该月有几天。星期几是从0(星期一)到 6(星期日)。
# (5, 30)解释:5 表示 2014 年 11 月份的第一天是周六,30 表示 2014 年 11 月份总共有 30 天。
print("calendar.monthrange(year,month):", calendar.monthrange(2016, 1))

# 相当于 print (calendar.calendar(year, w=0, l=0, c=6, m=3))。
calendar.prcal(2016, w=0, l=0, c=6, m=3)

# 相当于 print(calendar.month(theyear, themonth, w=0, l=0))。
calendar.prmonth(2016, 1, w=0, l=0)

# 设置每周的起始日期码。0(星期一)到6(星期日)。
calendar.setfirstweekday(6)

# 和time.gmtime相反:接受一个时间元组形式,返回该时刻的时间戳(1970纪元后经过的浮点秒数)。
# tm_year=2016, tm_mon=2, tm_mday=15, tm_hour=3, tm_min=56, tm_sec=49, tm_wday=0, tm_yday=46, tm_isdst=0
print(calendar.timegm((2016, 2, 15, 3, 56, 49, 0, 46, 0)))

# 返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。
# 输出 4 表示星期五
print("calendar.weekday(year,month,day):", calendar.weekday(2022, 9, 9))

random模块

Python random 模块主要用于生成随机数。

random 模块实现了各种分布的伪随机数生成器。

#!/usr/bin/python
# -*- coding: UTF-8 -*-

"""
随机数模块
"""
import random

# 查看 random 模块中的内容:
print(dir(random))

# 使用 random() 方法返回一个随机数, 在半开放区间 [0,1) 范围内,包含 0 但不包含 1
print(random.random())

# seed() 方法改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数。
random.seed()
print("使用默认种子生成随机数:", random.random())
random.seed(10)
print("使用整数 10 种子生成随机数:", random.random())
random.seed("hello", 2)
print("使用字符串种子生成随机数:", random.random())

# 从 range(start, stop, step) 返回一个随机选择的元素
print(random.randrange(1, 10))

# 返回随机整数 N 满足 a <= N <= b
print(random.randint(1, 20))

# choice() 方法返回一个列表,元组或字符串的随机项。
print("从 range(100) 返回一个随机数 : ", random.choice(range(100)))
print("从列表中 [1, 2, 3, 5, 9]) 返回一个随机元素 : ", random.choice([1, 2, 3, 5, 9]))
print("从字符串中 'Runoob' 返回一个随机字符 : ", random.choice('Runoob'))

# shuffle() 方法将序列的所有元素随机排序
list = [1, 2, 3, 5, 9]
random.shuffle(list)
print(list)

# 返回一个随机浮点数 N ,当 a <= b 时 a <= N <= b ,当 b < a 时 b <= N <= a 。
print("uniform(5, 10) 的随机浮点数 : ", random.uniform(5, 10))
print("uniform(7, 14) 的随机浮点数 : ", random.uniform(7, 14))

math模块

Python math 模块提供了许多对浮点数的数学运算函数。

math 模块下的函数,返回值均为浮点数,除非另有明确说明。

如果你需要计算复数,请使用 cmath 模块中的同名函数。

#!/usr/bin/python
# -*- coding: UTF-8 -*-

"""
数学模块
"""
import math

# 返回欧拉数 (2.718281828459045...)
print(math.e)

# 返回正无穷大浮点数
# 输出 inf
print(math.inf)

# 返回一个浮点值 NaN (not a number)
# 输出 nan
print(math.nan)

# π 一般指圆周率。 圆周率 PI (3.1415...)
print(math.pi)

# 数学常数 τ = 6.283185...,精确到可用精度。Tau 是一个圆周常数,等于 2π,圆的周长与半径之比。
print(math.tau)

# 以上这几个都是常量

# math.ceil(x) 将 x 向上舍入到最接近的整数,如果 x 不是一个数字,返回 TypeError。
print("math.ceil:", math.ceil(1.4))
print("math.ceil:", math.ceil(-5.3))

# math.dist(p, q) 返回 p 与 q 两点之间的欧几里得距离,以一个坐标序列(或可迭代对象)的形式给出。 两个点必须具有相同的维度。
p = [3, 3]
q = [6, 12]
# 计算欧几里得距离
print("math.dist:", math.dist(p, q))

# math.exp(x) 返回 e 的 x 次幂,Ex, 其中 e = 2.718281... 是自然对数的基数。
print("math.exp:", math.exp(65))
print("math.exp:", math.exp(-6.89))

# 返回 x 的绝对值。与 Python 内置的 abs() 不同,此方法始终将值转换为浮点值。
print("math.fabs:", math.fabs(2.77))
print("math.fabs:", math.fabs(-99.29))

# math.factorial(x) 返回 x 的阶乘。 如果 x 不是整数或为负数时则将引发 ValueError。
print("math.factorial:", math.factorial(9))

# math.floor() 将数字向下舍入到最接近的整数。如果 x 不是一个数字,返回 TypeError。
print("math.floor:", math.floor(0.6))
print("math.floor:", math.floor(-5.3))

# math.fmod(x, y) 返回 x/y 的余数。如果 x 和 y 不是一个数字,返回 TypeError。
# 注意:如果 x 和 y = 0,则返回 ValueError。
# 注意:如果 y = 0,则返回 ValueError。
# 注意:如果 x 或 y 不是数字,则返回 TypeError。
print("math.fmod:", math.fmod(20, 4))
print("math.fmod:", math.fmod(-10, 3))

# math.frexp(x) 以 (m, e) 对的形式返回 x 的尾数和指数。 m 是一个浮点数, e 是一个整数,正好是 x == m * 2**e 。 如果 x 为零,则返回 (0.0, 0) ,否则返回 0.5 <= abs(m) < 1 。
# 如果 x 不是一个数字,返回 TypeError。
print("math.frexp:", math.frexp(4))
print("math.frexp:", math.frexp(7))

# math.fsum(iterable) 返回可迭代对象 (元组, 数组, 列表, 等)中的元素总和,是浮点值。如果可迭代对象元素不是数字,返回 TypeError。
print("math.fsum:", math.fsum([1, 2, 3, 4, 5]))

# math.gcd() 返回给定的整数参数的最大公约数。如果 x 不是一个数字,返回 TypeError。
print("math.gcd:", math.gcd(3, 6))
print("math.gcd:", math.gcd(-12, -36))
print("math.gcd:", math.gcd(10, 0))
print("math.gcd:", math.gcd(0, 0))

# math.isclose(a, b) 检查两个值是否彼此接近,若 a 和 b 的值比较接近则返回 True,否则返回 False。
# a -- 必需,数字。如果 x 不是一个数字,返回 TypeError。如果值为 0 或负数,则返回 ValueError。
# b -- 必需,数字。如果 x 不是一个数字,返回 TypeError。如果值为 0 或负数,则返回 ValueError。
# rel_tol -- 是相对容差,它是 a 和 b 之间允许的最大差值,相对于 a 或 b 的较大绝对值。例如,要设置5%的容差,请传递 rel_tol=0.05 。默认容差为 1e-09,确保两个值在大约9位十进制数字内相同。 rel_tol 必须大于零。
# abs_tol -- 是最小绝对容差,对于接近零的比较很有用。 abs_tol 必须至少为零。
print("math.isclose:", math.isclose(8.005, 8.450, abs_tol=0.4))
print("math.isclose:", math.isclose(8.005, 8.450, abs_tol=0.5))

# math.isfinite(x) 判断 x 是否有限,如果 x 既不是无穷大也不是 NaN,则返回 True ,否则返回 False 。如果 x 不是一个数字,返回 TypeError。
print("math.isfinite:", math.isfinite(2000))
print("math.isfinite:", math.isfinite(-45.34))
print("math.isfinite:", math.isfinite(+45.34))
print("math.isfinite:", math.isfinite(math.inf))
print("math.isfinite:", math.isfinite(float("nan")))
print("math.isfinite:", math.isfinite(float("inf")))
print("math.isfinite:", math.isfinite(float("-inf")))
print("math.isfinite:", math.isfinite(-math.inf))
print("math.isfinite:", math.isfinite(0.0))

# math.isinf(x) 判断 x 是否是无穷大,如果 x 是正或负无穷大,则返回 True ,否则返回 False 。 如果 x 不是一个数字,返回 TypeError。
print("math.isinf:", math.isinf(2000))
print("math.isinf:", math.isinf(-45.34))
print("math.isinf:", math.isinf(+45.34))
print("math.isinf:", math.isinf(math.inf))
print("math.isinf:", math.isinf(float("nan")))
print("math.isinf:", math.isinf(float("inf")))
print("math.isinf:", math.isinf(float("-inf")))
print("math.isinf:", math.isinf(-math.inf))
print("math.isinf:", math.isinf(0.0))

# math.isnan() 判断数字是否为 NaN,如果 x 是 NaN(不是数字),则返回 True ,否则返回 False 。
print("math.isnan:", math.isnan(1))

# math.isqrt() 将平方根数向下舍入到最接近的整数
print("math.isqrt:", math.isqrt(10))

# math.log(x[, base]) 使用一个参数,返回 x 的自然对数(底为 e )。
print("math.log:", math.log(2.7183))

# math.log10(x) 返回 x 底为 10 的对数。
print("math.log10:", math.log10(100))

# math.log1p(x) 返回 1+x 的自然对数(以 e 为底)。
print("math.log1p:", math.log1p(2))

# math.log2(x) 返回 x 以 2 为底的对数
print("math.log2:", math.log2(4))

# math.pow(x, y) 将返回 x 的 y 次幂。
print("math.pow:", math.pow(2, 10))

# math.prod(iterable) 计算可迭代对象中所有元素的积。
print("math.prod:", math.prod([2, 5, 8]))

# math.remainder(x, y) 返回 IEEE 754 风格的 x 除于 y 的余数。
print("math.remainder:", math.remainder(10, 3))

# math.sqrt(x) 返回 x 的平方根。
print("math.sqrt:", math.sqrt(4))

# math.trunc(x) 返回 x 截断整数的部分,即返回整数部分,删除小数部分
print("math.trunc:", math.trunc(5.001))

operator模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
实现比较功能
常用的有:
* 加法:add(a, b)
* 减法:sub(a, b)
* 乘法:mul(a, b) -- a * b
* 除法:truediv(a, b) -- a/b
* 除法:floordiv(a, b) -- a//b
* 取模:mod(a, b) -- a % b

* 字符串拼接:concat(seq1, seq2)
* 包含测试:contains(seq, obj)
* 标识:is_(a, b) -- a is b
* 标识:is_not(a, b) -- a is not b
* 真值测试:truth(obj)
* 小于:lt(a, b) -- a < b
* 小于等于:le(a, b) -- a<=b
* 相等:eq(a, b)
* 不等:ne(a, b)
* 大于:gt(a, b)
* 大于等于:ge(a, b)

* 索引赋值:setitem(obj, k, v) -- obj[k] = v
* 索引删除:delitem(obj, k) -- del obj[k]
* 索引取值:getitem(obj, k) -- obj[k]
* 切片赋值:setitem(seq, slice(i, j), values) -- seq[i:j] = values
* 切片删除:delitem(seq, slice(i, j)) -- del seq[i:j]
* 切片取值: getitem(seq, slice(i, j)) -- seq[i:j]

* 左移:lshift(a, b) -- a << b
* 矩阵乘法:matmul(a, b) -- a @ b
* 取反(算术):neg(a) -- -a
* 取反(逻辑):not_(a) -- not a
* 正数:pos(a) -- +a
* 右移:rshift(a, b) -- a >> b
* 按位与:and_(a, b) -- a & b
* 按位异或:xor(a, b) -- a ^ b
* 按位取反:invert(a) -- ~ a
* 按位或:or_(a, b) -- a|b
* 取幂:pow(a, b) -- a ** b

"""
import operator

# 加减乘除运算
print("************加减乘除运算************")
x = 10
y = 4
print("x:", x, ", y:", y)
print("operator.add(x,y): ", operator.add(x, y))
print("operator.sub(x,y): ", operator.sub(x, y))
print("operator.mul(x,y): ", operator.mul(x, y))
print("operator.truediv(x,y): ", operator.truediv(x, y))
print("operator.floordiv(x,y): ", operator.floordiv(x, y))
print("operator.mod(x,y): ", operator.mod(x, y))
print()

#### 数字比较
print("************数字比较************")
x = 10
y = 20

print("x:", x, ", y:", y)
print("operator.lt(x,y): ", operator.lt(x, y))
print("operator.gt(y,x): ", operator.gt(y, x))
print("operator.eq(x,x): ", operator.eq(x, x))
print("operator.ne(y,y): ", operator.ne(y, y))
print("operator.le(x,y): ", operator.le(x, y))
print("operator.ge(y,x): ", operator.ge(y, x))
print()

#### 字符串比较
print("************字符串比较************")
x = "Google"
y = "Runoob"

print("x:", x, ", y:", y)
print("operator.lt(x,y): ", operator.lt(x, y))
print("operator.gt(y,x): ", operator.gt(y, x))
print("operator.eq(x,x): ", operator.eq(x, x))
print("operator.ne(y,y): ", operator.ne(y, y))
print("operator.le(x,y): ", operator.le(x, y))
print("operator.ge(y,x): ", operator.ge(y, x))
print()

#### 字符串操作
print("************字符串操作************")
x = "Google"
y = "Google World"

print("x:", x, ", y:", y)
print("operator.concat(x,y): ", operator.concat(x, y))
print("operator.contains(y,x): ", operator.contains(y, x))
print("operator.is_(y,y): ", operator.is_(y, y))
print("operator.is_not(x,y): ", operator.is_not(x, y))
print("operator.truth(y): ", operator.truth(y))
print()

# 查看返回值
print("type((operator.lt(x,y)): ", type(operator.lt(x, y)))

#### 序列操作
print("************序列操作************")
a = [1, 2, 3]
b = [2, 3, 4]
c = [2, 3, 4]
print("a = {0}, b = {1}, c= {2}".format(a, b, c))
print("operator.eq(a,b): ", operator.eq(a, b))
print("operator.eq(c,b): ", operator.eq(c, b))
print("operator.getitem(b, 1):", operator.getitem(b, 1))
operator.setitem(a, 0, 6)
print("operator.setitem(a, 0, 6): ", a)
operator.delitem(c, 0)
print("operator.delitem(c, 0):", c)
operator.setitem(a, slice(0, 2), [10, 11, 12, 14, 15])
print("operator.setitem(a, slice(0, 2), [10, 11]):", a)
operator.delitem(a, slice(0, 1))
print("operator.delitem(a, slice(0, 1)):", a)
print("operator.getitem(a, slice(0, 2)):", operator.getitem(a, slice(0, 2)))

logging模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-

"""
logging 模块定义了为应用程序和库实现灵活的事件日志记录的函数和类。
日志级别等级排序:critical > error > warning > info > debug
级别越高打印的日志越少,反之亦然,即
* debug : 打印全部的日志( notset 等同于 debug )
* info : 打印 info, warning, error, critical 级别的日志
* warning : 打印 warning, error, critical 级别的日志
* error : 打印 error, critical 级别的日志
* critical : 打印 critical 级别

logging 模块提供了两种日志记录方式:
* 一种方式是使用 Logging 提供的模块级别的函数
* 另一种方式是使用 Logging 日志系统的四大组件记录

"""
import logging

# ************************************* 使用 Logging 提供的模块级别的函数
"""
basicConfig()有很对参数可以配置:
1)filename:指定日志文件名;
2)filemode:和file函数意义相同,指定日志文件的打开模式,'w'或者'a';
3)format:指定输出的格式和内容,format可以输出很多有用的信息,
* %(levelno)s:打印日志级别的数值
* %(levelname)s:打印日志级别的名称
* %(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
* %(filename)s:打印当前执行程序名
* %(funcName)s:打印日志的当前函数
* %(lineno)d:打印日志的当前行号
* %(asctime)s:打印日志的时间
* %(thread)d:打印线程ID
* %(threadName)s:打印线程名称
* %(process)d:打印进程ID
* %(message)s:打印日志信息
4)datefmt:指定时间格式,同time.strftime();
5)level:设置日志级别,默认为logging.WARNING;
6)stream:指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略;

"""


# 打印日志级别
def test_logging():
    logging.basicConfig(filename='D:/example.log', level=logging.DEBUG, format='%(asctime)s %(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p')
    logging.debug('Python debug')
    logging.info('Python info')
    logging.warning('Python warning')
    logging.error('Python Error')
    logging.critical('Python critical')


test_logging()

# ************************** 使用 Logging 日志系统的四大组件记录
"""
日志器(logger)是入口,真正干活儿的是处理器(handler),
处理器(handler)还可以通过过滤器(filter)和格式器(formatter)对要输出的日志内容做过滤和格式化等处理操作。

Logger 可以包含一个或多个 Handler 和 Filter
Logger 与 Handler 或 Filter 是一对多的关系
一个 Logger 实例可以新增多 个 Handler,一个 Handler 可以新增多个格式化器或多个过滤器,而且日志级别将会继承。

"""

# ************ 组件一:初始化日志器 - Logger ************
# 多次使用相同的name调用 getLogger 方法返回同一个 logger 对象;
logger = logging.getLogger("testModule")

# Logging 中有 NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL这几种级别,日志会记录设置级别以上的日志
logger.setLevel(logging.DEBUG)

# logger.addHandler(handler_name)  # 为 Logger 实例增加一个处理器
# logger.removeHandler(handler_name)  # 为 Logger 实例删除一个处理器

# ************ 组件二:处理器- Handler ************
# Handler 处理器类型有很多种,比较常用的有三个,StreamHandler,FileHandler,NullHandler

## 创建 StreamHandler
sh = logging.StreamHandler(stream=None)

# sh.setLevel(logging.WARN)  # 指定日志级别,低于WARN级别的日志将被忽略
# sh.setFormatter(formatter_name)  # 设置一个格式化器formatter
# sh.addFilter(filter_name)  # 增加一个过滤器,可以增加多个
# sh.removeFilter(filter_name)  # 删除一个过滤器

# ************ 组件三:过滤器- Filter ************
# Handlers 和 Loggers 可以使用 Filters 来完成比级别更复杂的过滤。 Filter 基类只允许特定 Logger 层次以下的事件。
# 例如用 ‘A.B’ 初始化的 Filter 允许Logger ‘A.B’, ‘A.B.C’, ‘A.B.C.D’, ‘A.B.D’ 等记录的事件,logger‘A.BB’, ‘B.A.B’ 等就不行。
# 如果用空字符串来初始化,所有的事件都接受。

filter = logging.Filter(name='')

# ************ 组件四:格式器- Formatter ************
# 使用Formatter对象设置日志信息最后的规则、结构和内容,默认的时间格式为%Y-%m-%d %H:%M:%S。
# 其中,fmt 是消息的格式化字符串,datefmt 是日期字符串。如果不指明 fmt,将使用 '%(message)s' 。如果不指明 datefmt,将使用 ISO8601 日期格式。
# 注:%(name)s 对应的是这里的模块名字,如果不指定name则返回root对象。
formatter = logging.Formatter(fmt='%(asctime)s - %(thread)d - %(lineno)d - %(name)s', datefmt='%Y-%m-%d %H:%M:%S')

sh.setFormatter(formatter)
logger.addHandler(sh)
logger.addFilter(filter)


def logger2():
    logger.debug('Python debug')
    logger.info('Python info')
    logger.warning('Python warning')
    logger.error('Python Error')
    logger.critical('Python critical')

logger2()

程序员可以通过三种方式配置日志记录:
1)使用配置方法的 Python 代码显式创建记录器,处理程序和格式化程序。
2)创建日志记录配置文件并使用该 fileConfig() 功能读取它。
3)创建配置信息字典并将其传递给 dictConfig()函数。

logging.conf 配置文件

[loggers]
keys=root,simpleExample

[handlers]
keys=consoleHandler

[formatters]
keys=simpleFormatter

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_simpleExample]
level=DEBUG
handlers=consoleHandler
qualname=simpleExample
propagate=0

[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=simpleFormatter
args=(sys.stdout,)

[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=

config_logging.py 配置器

import logging
# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# 在别的.py文件中导入该对象:from config_logging import logger 即可使用logger对象
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

recorder 记录器

import logging
import logging.config

logging.config.fileConfig('logging.conf')

# create logger
logger = logging.getLogger('simpleExample')

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

os模块

#!/usr/bin/python
# -*- coding: UTF-8 -*-

"""
os 模块提供了非常丰富的方法用来处理文件和目录。
"""
import os
import os.path
import time

"""
os.open() 方法用于打开一个文件,并且设置需要的打开选项,模式参数mode参数是可选的,默认为 0777。
【语法】
os.open(file, flags[, mode]);
【参数】
1)file -- 要打开的文件
2)flags -- 该参数可以是以下选项,多个使用 "|" 隔开:
os.O_RDONLY: 以只读的方式打开
os.O_WRONLY: 以只写的方式打开
os.O_RDWR : 以读写的方式打开
os.O_NONBLOCK: 打开时不阻塞
os.O_APPEND: 以追加的方式打开
os.O_CREAT: 创建并打开一个新文件
os.O_TRUNC: 打开一个文件并截断它的长度为零(必须有写权限)
os.O_EXCL: 如果指定的文件存在,返回错误
os.O_SHLOCK: 自动获取共享锁
os.O_EXLOCK: 自动获取独立锁
os.O_DIRECT: 消除或减少缓存效果
os.O_FSYNC : 同步写入
os.O_NOFOLLOW: 不追踪软链接
【返回值】
返回新打开文件的描述符。

open() 和 os.open() 两者的区别主要是mode值不一致
"""
print("___________************ os.open()")
# 打开文件
fd = os.open("foo.txt", os.O_RDWR | os.O_CREAT)
# 写入字符串
os.write(fd, str.encode("This is test"))
# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.mkdir() 方法用于以数字权限模式创建目录。默认的模式为 0777 (八进制)。
如果目录有多级,则创建最后一级,如果最后一级目录的上级目录有不存在的,则会抛出一个 OSError。
【语法】
os.mkdir(path[, mode])
【参数】
path -- 要创建的目录,可以是相对或者绝对路径。
mode -- 要为目录设置的权限数字模式
"""
print("___________************ os.mkdir()")
# 创建的目录
path = "../home/"
if not os.path.exists(path):
    os.mkdir(path, 0o755)
    print("目录已创建")
else:
    print("{0}目录已存在".format(path))

"""
os.remove() 方法用于删除指定路径的文件。如果指定的路径是一个目录,将抛出OSError。
在Unix, Windows中有效。
【语法】
os.remove(path)
【参数】
path -- 要移除的文件路径
"""
print("___________************ os.remove()")
# 列出目录
print("目录为: %s" % os.listdir(os.getcwd()))
# 移除
path = "bar.txt"
if os.path.exists(path):
    os.remove(path)
else:
    print("{0}文件不存在, 无需删除".format(path))
# 移除后列出目录
print("移除后 : %s" % os.listdir(os.getcwd()))

"""
os.removedirs() 方法用于递归删除目录。
像rmdir(), 如果子文件夹成功删除, removedirs()才尝试它们的父文件夹,直到抛出一个error(它基本上被忽略,因为它一般意味着你文件夹不为空)。
【语法】
os.removedirs(path)
【参数】
path -- 要移除的目录路径

"""
print("___________************ os.removedirs()")
# 列出目录
print("目录为: %s" % os.listdir(os.getcwd()))
# 移除
path = "../home"
if os.path.exists(path):
    os.removedirs(path)
# 列出移除后的目录
print("移除后目录为:" % os.listdir(os.getcwd()))

"""
os.rename() 方法用于命名文件或目录,从 src 到 dst,如果dst是一个存在的目录, 将抛出OSError。
【语法】
os.rename(src, dst)
【参数】
src -- 要修改的目录名
dst -- 修改后的目录名
"""
print("___________************ os.rename()")
# 列出目录
print("目录为: %s" % os.listdir(os.getcwd()))
# 重命名
try:
    os.rename("test", "test2")
    print("重命名成功。")
except:
    pass

# 列出重命名后的目录
print("目录为: %s" % os.listdir(os.getcwd()))

"""
os.renames() 方法用于递归重命名目录或文件。类似rename()。
【语法】
os.renames(old, new)
【参数】
old -- 要重命名的目录
new --文件或目录的新名字。甚至可以是包含在目录中的文件,或者完整的目录树。
"""
print("___________************ os.renames()")
print("当前目录为: %s" % os.getcwd())
# 列出目录
print("目录为: %s" % os.listdir(os.getcwd()))
# 重命名 "aa1.txt"
try:
    os.renames("aa1.txt", "fei.txt")
    print("重命名成功。")
except:
    pass
# 列出重命名的文件 "aa1.txt"
print("目录为: %s" % os.listdir(os.getcwd()))

"""
os.rmdir() 方法用于删除指定路径的目录。仅当这文件夹是空的才可以, 否则, 抛出OSError。
【语法】
os.rmdir(path)
【参数】
path -- 要删除的目录路径
"""
print("___________************ os.rmdir()")
# 列出目录
print("目录为: %s" % os.listdir(os.getcwd()))
# 删除路径
path = "../mydir"
if os.path.exists(path):
    os.rmdir("../mydir")
# 列出重命名后的目录
print("目录为: %s" % os.listdir(os.getcwd()))

"""
os.stat() 方法用于在给定的路径上执行一个系统 stat 的调用。
【语法】
os.stat(path)
【参数】
path -- 指定路径
【返回值】
stat 结构:
1)st_mode: inode 保护模式
2)st_ino: inode 节点号。
3)st_dev: inode 驻留的设备。
4)st_nlink: inode 的链接数。
5)st_uid: 所有者的用户ID。
6)st_gid: 所有者的组ID。
7)st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。
8)st_atime: 上次访问的时间。
9)st_mtime: 最后一次修改的时间。
10)st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
"""
print("___________************ os.stat()")
# 显示文件 "client.py" 信息
statinfo = os.stat('client.py')
print(statinfo)

"""
os.unlink() 方法用于删除文件,如果文件是一个目录则返回一个错误。
【语法】
os.unlink(path)
【参数】
path -- 删除的文件路径
"""
print("___________************ os.unlink()")
# 列出目录
print("目录为: %s" % os.listdir(os.getcwd()))
path = "fei.txt"
if os.path.exists(path):
    os.unlink("fei.txt")

# 删除后的目录
print("删除后的目录为 : %s" % os.listdir(os.getcwd()))

"""
os.utime() 方法用于设置指定路径文件最后的修改和访问时间。
在Unix,Windows中有效。
【语法】
os.utime(path, times)
【参数】
path -- 文件路径
times -- 如果时间是 None, 则文件的访问和修改设为当前时间 。 否则, 时间是一个 2-tuple数字, (atime, mtime) 用来分别作为访问和修改的时间。
"""
print("___________************ os.utime()")
# 显示文件的 stat 信息
stinfo = os.stat('client.py')
print(stinfo)

# 使用 os.stat 来接收文件的访问和修改时间
print("client.py 的访问时间: %s" % stinfo.st_atime)
print("client.py 的修改时间: %s" % stinfo.st_mtime)
# 修改访问和修改时间
os.utime("client.py", (1330712280, 1330712292))
print("done!!")

"""
os.pardir() 获取当前目录的父目录(上一级目录),以字符串形式显示目录名。
注意: Windows 和 POSIX 返回 ..。
"""
print("___________************ os.pardir")
print(os.pardir)

"""
os.write() 方法用于写入字符串到文件描述符 fd 中. 返回实际写入的字符串长度。
在Unix中有效。
【语法】
os.write(fd, str)
【参数】
fd -- 文件描述符。
str -- 写入的字符串。
【返回值】
该方法返回写入的实际位数。
"""
print("___________************ os.write()")
# 打开文件
fd = os.open("f1.txt", os.O_RDWR | os.O_CREAT)
# 写入字符串
str1 = "This is runoob.com site"
ret = os.write(fd, bytes(str1, 'UTF-8'))
# 输入返回值
print("写入的位数为: ", ret)
print("写入成功")

# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.path 模块主要用于获取文件的属性。
常用的属性有:
os.path.abspath(path)	返回绝对路径
os.path.basename(path)	返回文件名
os.path.commonprefix(list)	返回list(多个路径)中,所有path共有的最长的路径
os.path.dirname(path)	返回文件路径
os.path.exists(path)	路径存在则返回True,路径损坏返回False
os.path.lexists	路径存在则返回True,路径损坏也返回True
os.path.expanduser(path)	把path中包含的"~"和"~user"转换成用户目录
os.path.expandvars(path)	根据环境变量的值替换path中包含的"$name"和"${name}"
os.path.getatime(path)	返回最近访问时间(浮点型秒数)
os.path.getmtime(path)	返回最近文件修改时间
os.path.getctime(path)	返回文件 path 创建时间
os.path.getsize(path)	返回文件大小,如果文件不存在就返回错误
os.path.isabs(path)	判断是否为绝对路径
os.path.isfile(path)	判断路径是否为文件
os.path.isdir(path)	判断路径是否为目录
os.path.islink(path)	判断路径是否为链接
os.path.ismount(path)	判断路径是否为挂载点
os.path.join(path1[, path2[, ...]])	把目录和文件名合成一个路径
os.path.normcase(path)	转换path的大小写和斜杠
os.path.normpath(path)	规范path字符串形式
os.path.realpath(path)	返回path的真实路径
os.path.relpath(path[, start])	从start开始计算相对路径
os.path.samefile(path1, path2)	判断目录或文件是否相同
os.path.sameopenfile(fp1, fp2)	判断fp1和fp2是否指向同一文件
os.path.samestat(stat1, stat2)	判断stat tuple stat1和stat2是否指向同一个文件
os.path.split(path)	把路径分割成 dirname 和 basename,返回一个元组
os.path.splitdrive(path)	一般用在 windows 下,返回驱动器名和路径组成的元组
os.path.splitext(path)	分割路径中的文件名与拓展名
os.path.splitunc(path)	把路径分割为加载点与文件
os.path.walk(path, visit, arg)	遍历path,进入每个目录都调用visit函数,visit函数必须有3个参数(arg, dirname, names),dirname表示当前目录的目录名,names代表当前目录下的所有文件名,args则为walk的第三个参数
os.path.supports_unicode_filenames	设置是否支持unicode路径名
"""
print("___________************ os.path")

# 当前文件名
print(__file__)

# 当前文件名的绝对路径
print(os.path.abspath(__file__))

# 返回当前文件的路径
print(os.path.dirname(os.path.abspath(__file__)))

print(os.path.basename('runoob.txt'))  # 返回文件名
print(os.path.dirname('runoob.txt'))  # 返回目录路径
print(os.path.split('runoob.txt'))  # 分割文件名与路径
print(os.path.join('root', 'test', 'runoob.txt'))  # 将目录和文件名合成一个路径

file = 'runoob.txt'  # 文件路径
print(os.path.getatime(file))  # 输出最近访问时间
print(os.path.getctime(file))  # 输出文件创建时间
print(os.path.getmtime(file))  # 输出最近修改时间
print(time.gmtime(os.path.getmtime(file)))  # 以struct_time形式输出最近修改时间
print(os.path.getsize(file))  # 输出文件大小(字节为单位)
print(os.path.abspath(file))  # 输出绝对路径
print(os.path.normpath(file))  # 规范path字符串形式

"""
os.read() 方法用于从文件描述符 fd 中读取最多 n 个字节,返回包含读取字节的字符串,文件描述符 fd对应文件已达到结尾, 返回一个空字符串。
在Unix,Windows中有效。
【语法】
os.read(fd,n)
【参数】
fd -- 文件描述符。
n -- 读取的字节。
【返回值】
返回包含读取字节的字符串
"""
print("___________************ os.read()")
# 打开文件
fd = os.open("foo.txt", os.O_RDWR)

# 读取文本
ret = os.read(fd, 12)
print(ret)

# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.lseek() 方法用于设置文件描述符 fd 当前位置为 pos, how 方式修改。
在Unix,Windows中有效。
【语法】
os.lseek(fd, pos, how)
【参数】
1)fd -- 文件描述符。
2)pos -- 这是相对于给定的参数 how 在文件中的位置。。
3)how -- 文件内参考位置。SEEK_SET 或者 0 设置从文件开始的计算的pos; SEEK_CUR或者 1 则从当前位置计算; os.SEEK_END或者2则从文件尾部开始。
"""
print("___________************ os.lseek()")
# 打开文件
fd = os.open("foo.txt", os.O_RDWR | os.O_CREAT)
# 写入字符串
os.write(fd, "This is test".encode("utf-8"))
# 所有 fsync() 方法
os.fsync(fd)
# 从开始位置读取字符串
os.lseek(fd, 0, 0)
str1 = os.read(fd, 100)
print("Read String is : ", str1)
# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。这个列表以字母顺序。 它不包括 . 和 .. 即使它在文件夹中。
只支持在 Unix, Windows 下使用。
【语法】
os.listdir(path)
【参数】
path -- 需要列出的目录路径
【返回值】
返回指定路径下的文件和文件夹列表。
"""
print("___________************ os.listdir()")
# 打开文件
path = "../demo"
dirs = os.listdir(path)

# 输出所有文件和文件夹
for file in dirs:
    print(file)

"""
os.getcwd() 方法用于返回当前工作目录。
"""
print("___________************ os.getcwd()")
# 打印当前目录
print("当前工作目录 : %s" % os.getcwd())

"""
os.fsync() 方法强制将文件描述符为fd的文件写入硬盘。在Unix, 将调用fsync()函数;在Windows, 调用 _commit()函数。
如果你准备操作一个Python文件对象f, 首先f.flush(),然后os.fsync(f.fileno()), 确保与f相关的所有内存都写入了硬盘.在unix,Windows中有效。
Unix、Windows上可用。
【语法】
os.fsync(fd)
【参数】
fd -- 文件的描述符。
"""
print("___________************ os.fsync()")
# 打开文件
fd = os.open("foo.txt", os.O_RDWR | os.O_CREAT)
# 写入字符串
os.write(fd, "This is liuliu".encode("UTF-8"))
# 使用 fsync() 方法.
os.fsync(fd)
# 读取内容
os.lseek(fd, 0, 0)
str1 = os.read(fd, 100)
print("读取的字符串为 : ", str1)
# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.fstat() 方法用于返回文件描述符fd的状态,类似 stat()。
Unix,Windows上可用。
fstat 方法返回的结构:
1)st_dev: 设备信息
2)st_ino: 文件的i-node值
3)st_mode: 文件信息的掩码,包含了文件的权限信息,文件的类型信息(是普通文件还是管道文件,或者是其他的文件类型)
4)st_nlink: 硬连接数
5)st_uid: 用户ID
6)st_gid: 用户组 ID
7)st_rdev: 设备 ID (如果指定文件)
8)st_size: 文件大小,以byte为单位
9)st_blksize: 系统 I/O 块大小
10)st_blocks: 文件的是由多少个 512 byte 的块构成的
11)st_atime: 文件最近的访问时间
12)st_mtime: 文件最近的修改时间
13)st_ctime: 文件状态信息的修改时间(不是文件内容的修改时间)
"""
print("___________************ os.fstat()")
# 打开文件
fd = os.open("foo.txt", os.O_RDWR | os.O_CREAT)
# 获取元组
info = os.fstat(fd)
print("文件信息 :", info)
# 获取文件 uid
print("文件 UID :%d" % info.st_uid)
# 获取文件 gid
print("文件 GID  :%d" % info.st_gid)
# 关闭文件
os.close(fd)

"""
os.fdopen(fd[, mode[, bufsize]]) 通过文件描述符 fd 创建一个文件对象,并返回这个文件对象
【参数】
1)fd -- 打开的文件的描述符,在Unix下,描述符是一个小整数。
2)mode -- 可选,和 Python 内建的 open 函数一样,mode参数可以指定『r,w,a,r+,w+,a+,b』等,表示文件的是只读的还是可以读写的,
以及打开文件是以二进制还是文本形式打开。这些参数和C语言中的<stdio.h>中fopen函数中指定的mode参数类似。
3)bufsize -- 可选,指定返回的文件对象是否带缓冲:
bufsize=0,表示没有带缓冲;
bufsize=1,表示该文件对象是行缓冲的;
bufsize=正数,表示使用一个指定大小的缓冲冲,单位为byte,但是这个大小不是精确的;
bufsize=负数,表示使用一个系统默认大小的缓冲,对于tty字元设备一般是行缓冲,而对于其他文件则一般是全缓冲。
如果这个参数没有制定,则使用系统默认的缓冲设定。
【返回值】
通过文件描述符返回的文件对象。
"""
print("___________************ os.fdopen()")
# 打开文件
fd = os.open("foo.txt", os.O_RDWR | os.O_CREAT)
# 获取以上文件的对象
fo = os.fdopen(fd, "w+")
# 获取当前位置
print("Current I/O pointer position :%d" % fo.tell())
# 写入字符串
fo.write("Python is a great language.\nYeah its great!!\n")
# 读取内容
os.lseek(fd, 0, 0)
str1 = os.read(fd, 100)
print("Read String is : ", str1)
# 获取当前位置
print("Current I/O pointer position :%d" % fo.tell())
# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.fdatasync(fd) 用于强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。如果你需要刷新缓冲区可以使用该方法。
"""
print("___________************ os.fdatasync()")
# 打开文件
fd = os.open("test.txt", os.O_RDWR | os.O_CREAT)
# 写入字符串
os.write(fd, "This is test".encode("UTF-8"))
# 使用 fdatasync() 方法
try:
    os.fdatasync(fd)
except:
    pass
# 读取文件
os.lseek(fd, 0, 0)
contentByte = os.read(fd, 100)
print("读取的字符是 : ", contentByte.decode("UTF_8"))
# 关闭文件
os.close(fd)
print("关闭文件成功!!")

"""
os.access(path, mode) 检查是否有访问的权限
mode的可选项:
1)os.F_OK: 作为access()的mode参数,测试path是否存在。
2)os.R_OK: 包含在access()的mode参数中 , 测试path是否可读。
3)os.W_OK 包含在access()的mode参数中 , 测试path是否可写。
4)os.X_OK 包含在access()的mode参数中 ,测试path是否可执行。
"""
print("___________************ os.access()")
ret = os.access('test.txt', os.F_OK)
print("F_OK - 返回值 {0}".format(ret))

"""
os.chdir(path) 用于改变当前工作目录到指定的路径
"""
print("___________************ os.chdir()")
path = "/tmp"
# 查看当前工作目录
retval = os.getcwd()
print("当前工作目录为 {0}".format(retval))
# 修改当前工作目录
os.chdir(path)
# 查看修改后的工作目录
retval = os.getcwd()
print("目录修改成功 {0}".format(retval))

"""
os.dup(fd) 用于更改文件或目录的权限
"""
print("___________************ os.dup()")
# 打开文件
fd = os.open("test.txt", os.O_RDWR | os.O_CREAT)
# 复制文件描述符
d_fd = os.dup(fd)
# 使用复制的文件描述符写入文件
os.write(d_fd, "This is test1111".encode())

# 关闭文件
os.closerange(fd, d_fd)
print("关闭所有文件成功!!")

"""
os.dup2() 方法用于将一个文件描述符 fd 复制到另一个 fd2
#如果后面还有其他语句,则这样最好注释掉,否则后面的print输出全都写入到了test.txt文件
"""
print("___________************ os.dup2()")
# 打开一个文件
f = open('test.txt', 'a')  # mode为a表示追加模式
# 将这个文件描述符代表的文件,传递给 1 描述符指向的文件(也就是 stdout)
os.dup2(f.fileno(), 1)
# 关闭文件
f.close()
# print 输出test.txt文件
print('runoob')
print('google')

json模块

# -*- coding: UTF-8 -*-
"""
json模块是python内置的库,在使用的时候直接导入就可以。
json模块的操作使用相对较为简单,该模块只有四个方法dump()、load()、dumps()、loads()。
json模块的主要功能是将序列化数据从文件里读取出来或者存入文件。
其中dump()是将数据存入文件中,load()是用于读取文件。
而dumps()和loads()是对python对象进行操作。dumps()是将python对象编码成json字符串。loads()是将json字符串解码成python对象。

json.dumps()和json.dump()的区别:
json.dumps() 是把python对象转换成json对象的一个过程,生成的是字符串。
json.dump() 是把python对象转换成json对象生成一个fp的文件流,和文件相关。

json.loads()和json.load()的区别同上类似,加上s的方法是用来处理字符串类型的,而不加s是用来处理文件类型的。
"""
import json

# **** json.dumps():对数据进行编码,形成json格式的数据。
data_dict = {"key2": "value2", "key1": "value", "key3": "value3"}
# 默认转换的json数据是无序的。如果将参数sort_keys改为True, 则会根据key值将数据进行排序。
json1 = json.dumps(data_dict, sort_keys=True)
# 默认无序
json2 = json.dumps(data_dict)
print(json1)
print(json2)
# 输出{"key1": "value", "key2": "value2", "key3": "value3"}
# 输出{"key2": "value2", "key1": "value", "key3": "value3"}

# **** json.loads():和dumps相反,loads函数则是将json格式的数据解码,转换为Python字典。
data_str = '{"key1": "value1", "key2": "value2", "key3": "value3"}'
data_dict = json.loads(data_str)
print(data_dict)
# 输出:{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}


# **** json.dump()和json.load():与dumps()和loads的功能相似,只不过dump()和load是处理文件的。
data = '{"key1": "value1", "key2": "value2", "key3": "value3"}'
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f)  # 将数据写入到文件中
# 等同于f.write(json.dumps(data))

with open('data.json', 'r') as f:
    infos = json.load(f)  # 从文件中读取数据
    print(infos)
# infos = json.loads(f.read())#和上面的效果一样

Python 编码为 JSON 类型转换对应表:

Python JSON
dict object
list, tuple array
str string
int, float, int- & float-derived Enums number
True true
False false
None null

re模块

# -*- coding: UTF-8 -*-
import re

"""
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

#### re.match(pattern, string, flags=0) ####

匹配成功re.match方法返回一个匹配的对象,否则返回None。
* pattern 要匹配的正则表达式
* string 要匹配的字符串。
* flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
    1)re.I 使匹配对大小写不敏感
    2)re.L做本地化识别(locale-aware)匹配
    3)re.S 使 . 匹配包括换行在内的所有字符
    4)re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
    
可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
1)group(num=0)
匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
2)groups()
返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

"""
print(re.match('www', 'www.runoob.com').span())  # 在起始位置匹配
print(re.match('com', 'www.runoob.com'))  # 不在起始位置匹配

line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match(r'(.*) are (.*?) .*', line, re.M | re.I)
if matchObj:
    print("matchObj.group() : ", matchObj.group())
    print("matchObj.group(1) : ", matchObj.group(1))
    print("matchObj.group(2) : ", matchObj.group(2))  # group(2)第二组,即第二个()
else:
    print("No match!!")

"""
re.search方法 扫描整个字符串并返回第一个成功的匹配。

#### re.search(pattern, string, flags=0) ####

* pattern 要匹配的正则表达式
* string 要匹配的字符串。
* flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
    1)re.I 使匹配对大小写不敏感
    2)re.L做本地化识别(locale-aware)匹配
    3)re.S 使 . 匹配包括换行在内的所有字符
    4)re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
    
可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
1)group(num=0)
匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
2)groups()
返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

"""

print(re.search('www', 'www.runoob.com').span())  # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span())  # 不在起始位置匹配

line = "Cats are smarter than dogs"
searchObj = re.search(r'(.*) are (.*?) .*', line, re.M | re.I)
if searchObj:
    print("searchObj.group() : ", searchObj.group())
    print("searchObj.group(1) : ", searchObj.group(1))
    print("searchObj.group(2) : ", searchObj.group(2))
else:
    print("Nothing found!!")

"""
re.match与re.search的区别
re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 re.search 匹配整个字符串,直到找到一个匹配。
"""
line = "Cats are smarter than dogs"

matchObj = re.match(r'dogs', line, re.M | re.I)
if matchObj:
    print("match --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")

matchObj = re.search(r'dogs', line, re.M | re.I)
if matchObj:
    print("search --> matchObj.group() : ", matchObj.group())
else:
    print("No match!!")

"""
re.sub用于替换字符串中的匹配项。

#### re.sub(pattern, repl, string, count=0, flags=0) ####

参数:
1)pattern : 正则中的模式字符串。
2)repl : 替换的字符串,也可为一个函数。
3)string : 要被查找替换的原始字符串。
4)count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
5)flags : 编译时用的匹配模式,数字形式。
前三个为必选参数,后两个为可选参数。
"""
phone = "2004-959-559 # 这是一个电话号码"

# 删除注释
num = re.sub(r'#.*$', "", phone)
print("电话号码 : ", num)

# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print("电话号码 : ", num)

"""
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用

#### re.compile(pattern[, flags]) ####

参数:
1)pattern : 一个字符串形式的正则表达式
2)flags 可选,表示匹配模式,比如忽略大小写,多行模式等。

"""
pattern = re.compile(r'\d+')  # 用于匹配至少一个数字
m = pattern.match('one12twothree34four')  # 查找头部,没有匹配
print(m)

m = pattern.match('one12twothree34four', 2, 10)  # 从'e'的位置开始匹配,没有匹配
print(m)

m = pattern.match('one12twothree34four', 3, 10)  # 从'1'的位置开始匹配,正好匹配
print(m)  # 返回一个 Match 对象
m.group(0)  # 可省略 0
m.start(0)  # 可省略 0
m.end(0)  # 可省略 0
m.span(0)  # 可省略 0

"""
在上面,当匹配成功时返回一个 Match 对象,其中:
group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
span([group]) 方法返回 (start(group), end(group))。
"""
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)  # re.I 表示忽略大小写
m = pattern.match('Hello World Wide Web')
print(m)  # 匹配成功,返回一个 Match 对象
m.group(0)  # 返回匹配成功的整个子串
m.span(0)  # 返回匹配成功的整个子串的索引
m.group(1)  # 返回第一个分组匹配成功的子串
m.span(1)  # 返回第一个分组匹配成功的子串的索引
m.group(2)  # 返回第二个分组匹配成功的子串
m.span(2)  # 返回第二个分组匹配成功的子串索引
m.groups()  # 等价于 (m.group(1), m.group(2), ...)
# m.group(3)  # 不存在第三个分组,会报错 IndexError: no such group

"""
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。
注意: match 和 search 是匹配一次 findall 匹配所有。

语法格式为:
re.findall(pattern, string, flags=0)
或
pattern.findall(string[, pos[, endpos]])

参数:
1)pattern 匹配模式。
2)string 待匹配的字符串。
3)pos 可选参数,指定字符串的起始位置,默认为 0。
4)endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
"""
# 查找字符串中的所有数字
result1 = re.findall(r'\d+', 'runoob 123 google 456')

pattern = re.compile(r'\d+')  # 查找数字
result2 = pattern.findall('runoob 123 google 456')
result3 = pattern.findall('run88oob123google456', 0, 10)

print(result1)
print(result2)
print(result3)

# 多个匹配模式,返回元组列表:
result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)

"""
re.finditer(pattern, string, flags=0)
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

参数:
* pattern 要匹配的正则表达式
* string 要匹配的字符串。
* flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

"""
it = re.finditer(r"\d+", "12a32bc43jf3")
for match in it:
    print(match.group())

"""
re.split(pattern, string[, maxsplit=0, flags=0])
split 方法按照能够匹配的子串将字符串分割后返回列表
参数:
1)pattern	匹配的正则表达式
2)string	要匹配的字符串。
3)maxsplit	分割次数,maxsplit=1 分割一次,默认为 0,不限制次数。
4)flags	标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

"""
re.split('\W+', 'runoob, runoob, runoob.')
re.split('(\W+)', ' runoob, runoob, runoob.')
re.split('\W+', ' runoob, runoob, runoob.', 1)
re.split('a*', 'hello world')  # 对于一个找不到匹配的字符串而言,split 不会对其作出分割

"""
正则表达式模式:
^	匹配字符串的开头
$	匹配字符串的末尾。
.	匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...]	用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...]	不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re*	匹配0个或多个的表达式。
re+	匹配1个或多个的表达式。
re?	匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n}	匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。
re{ n,}	精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。
re{ n, m}	匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b	匹配a或b
(re)	匹配括号内的表达式,也表示一个组
(?imx)	正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx)	正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re)	类似 (...), 但是不表示一个组
(?imx: re)	在括号中使用i, m, 或 x 可选标志
(?-imx: re)	在括号中不使用i, m, 或 x 可选标志
(?#...)	注释.
(?= re)	前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)	前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re)	匹配的独立模式,省去回溯。
\w	匹配数字字母下划线
\W	匹配非数字字母下划线
\s	匹配任意空白字符,等价于 [\t\n\r\f]。
\S	匹配任意非空字符
\d	匹配任意数字,等价于 [0-9]。
\D	匹配任意非数字
\A	匹配字符串开始
\Z	匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z	匹配字符串结束
\G	匹配最后匹配完成的位置。
\b	匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B	匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等。	匹配一个换行符。匹配一个制表符, 等
\1...\9	匹配第n个分组的内容。
\10	匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。
"""

"""
正则表达式实例

python	匹配 "python"

[Pp]ython	匹配 "Python" 或 "python"
rub[ye]	匹配 "ruby" 或 "rube"
[aeiou]	匹配中括号内的任意一个字母
[0-9]	匹配任何数字。类似于 [0123456789]
[a-z]	匹配任何小写字母
[A-Z]	匹配任何大写字母
[a-zA-Z0-9]	匹配任何字母及数字
[^aeiou]	除了aeiou字母以外的所有字符
[^0-9]	匹配除了数字外的字符

.	匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
\d	匹配一个数字字符。等价于 [0-9]。
\D	匹配一个非数字字符。等价于 [^0-9]。
\s	匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S	匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w	匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W	匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。

"""

hashlib模块

# -*- coding: UTF-8 -*-
"""
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。

什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。
而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。

加密之后的密文数据是没有办法反解密成明文数据的
市面上所谓的破解 其实就是提前算出一系列明文对应的密文之后比对密文再获取明文

密文数据越长表示内部对应的算法越复杂 越难被正向破解
但是越复杂的算法所需要消耗的资源也就越多 密文越长基于网络发送需要占据的数据也就越大
具体使用什么算法取决于项目的要求 一般情况下md5足够了
"""

import hashlib

# *********** md5加密算法
# 先确定算法类型
md5 = hashlib.md5()
# 将明文数据传递给md5算法(update只能接受bytes类型数据)
md5.update('how to use md5 in python hashlib?'.encode("utf-8"))
# 获取加密之后的密文数据(没有规则的一串随机字符串)
print(md5.hexdigest())

# 如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
md5 = hashlib.md5()
md5.update('how to use md5 in ')
md5.update('python hashlib?')
print(md5.hexdigest())

# 加盐处理:在对明文数据做加密处理过程前添加一些干扰项
md5 = hashlib.md5()
md5.update('123'.encode('utf8'))
# # 加盐(干扰项)
md5.update('公司内部自己定义的盐'.encode('utf8'))
print(md5.hexdigest())

# 动态加盐(干扰项)  当前时间 用户名的部分 uuid(随机字符串(永远不会重复))
import time

res1 = str(time.time())
md5.update(res1.encode('utf8'))
print(md5.hexdigest())

# *********** 还有其他算法sha256/sha384/sha512等
sha256 = hashlib.sha256()
print(sha256.update("123"))

hmac模块

# -*- coding: UTF-8 -*-
"""
hashlib,hmac这两个都是Python中加密的函数,都是不可逆的加密,都是内置模块,直接导入即可使用。
hashlib模块实现了sha1,sha224,sha256,sha384,sha512,md5等算法,交易所的加密中一般使用sha256或md5
hmac模块需要一个msg来进行加密,hashlib并没有msg这个参数。
即使在hmac中把msg设为空,它仍旧会把这个空值进行hash运算,所以和hashlib算出来的结果也不一样,这就是问题所在。
也就是在使用中,如果有msg参数就使用hmac,否则使用hashlib就行了。

"""
import hashlib
import hmac

# key 加密的密钥
# msg 加密的信息
# digestmod是用于计算摘要的算法, hashlib模块有的加密算法都可以
h = hmac.new("harvey".encode("UTF-8"), "123456".encode("UTF-8"), digestmod="md5")
print(h.hexdigest())

urllib模块

# -*- coding: UTF-8 -*-
"""
Python urllib 库用于操作网页 URL,并对网页的内容进行抓取处理。
urllib 包 包含以下几个模块:
- urllib.request - 打开和读取 URL。
- urllib.error - 包含 urllib.request 抛出的异常。
- urllib.parse - 解析 URL。
- urllib.robotparser - 解析 robots.txt 文件。
"""

"""
urllib.request 定义了一些打开 URL 的函数和类,包含授权验证、重定向、浏览器 cookies等。
urllib.request 可以模拟浏览器的一个请求发起过程。
我们可以使用 urllib.request 的 urlopen 方法来打开一个 URL,语法格式如下:

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

参数列表:
* url:url 地址。
* data:发送到服务器的其他数据对象,默认为 None。
* timeout:设置访问超时时间。
* cafile 和 capath:cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。
* cadefault:已经被弃用。
* context:ssl.SSLContext类型,用来指定 SSL 设置。
"""
import urllib.request
from urllib.error import HTTPError

# urlopen 打开一个 URL,然后使用 read() 函数获取网页的 HTML 实体代码。
myURL = urllib.request.urlopen("https://www.runoob.com/")
print(myURL.read())
# 指定长度读取
myURL = urllib.request.urlopen("https://www.runoob.com/")
print(myURL.read(300))
# 读取文件的一行内容
myURL = urllib.request.urlopen("https://www.runoob.com/")
print(myURL.readline())
# 读取文件的全部内容,它会把读取的内容赋值给一个列表变量。
myURL = urllib.request.urlopen("https://www.runoob.com/")
lines = myURL.readlines()
for line in lines:
    print(line)

# 我们在对网页进行抓取时,经常需要判断网页是否可以正常访问,
# 这里我们就可以使用 getcode() 函数获取网页状态码,返回 200 说明网页正常,返回 404 说明网页不存在:
myURL1 = urllib.request.urlopen("https://www.runoob.com/")
print(myURL1.getcode())  # 200

try:
    myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html")
except HTTPError as e:
    if e.code == 404:
        print(404)  # 404

# 如果要将抓取的网页保存到本地
# 执行以下代码,在本地就会生成一个 runoob_urllib_test.html 文件,里面包含了 https://www.runoob.com/ 网页的内容。
myURL = urllib.request.urlopen("https://www.runoob.com/")
f = open("runoob_urllib_test.html", "wb")
content = myURL.read()  # 读取网页内容
f.write(content)
f.close()

encode_url = urllib.request.quote("https://www.runoob.com/")  # 编码
print(encode_url)

unencode_url = urllib.request.unquote(encode_url)  # 解码
print(unencode_url)

"""
我们抓取网页一般需要对 headers(网页头信息)进行模拟,这时候需要使用到 urllib.request.Request 类:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

参数:
* url:url 地址。
* data:发送到服务器的其他数据对象,默认为 None。
* headers:HTTP 请求的头部信息,字典格式。
* origin_req_host:请求的主机地址,IP 或域名。
* unverifiable:很少用整个参数,用于设置网页是否需要验证,默认是False。。
* method:请求方法, 如 GET、POST、DELETE、PUT等。

"""
import urllib.parse

url = 'https://www.runoob.com/?s='  # 菜鸟教程搜索页面
keyword = 'Python 教程'
key_code = urllib.request.quote(keyword)  # 对请求进行编码
url_all = url + key_code
header = {
    'User-Agent': 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}  # 头部信息
request = urllib.request.Request(url_all, headers=header)
response = urllib.request.urlopen(request).read()

fh = open("urllib_test_runoob_search.html", "wb")  # 将文件写入到当前目录中
fh.write(response)
fh.close()

"""
urllib.error 模块为 urllib.request 所引发的异常定义了异常类,基础异常类是 URLError。
urllib.error 包含了两个方法,URLError 和 HTTPError。
URLError 是 OSError 的一个子类,用于处理程序在遇到问题时会引发此异常(或其派生的异常),包含的属性 reason 为引发异常的原因。
HTTPError 是 URLError 的一个子类,用于处理特殊 HTTP 错误例如作为认证请求的时候,包含的属性 code 为 HTTP 的状态码, 
reason 为引发异常的原因,headers 为导致 HTTPError 的特定 HTTP 请求的 HTTP 响应头。
"""

# 对不存在的网页抓取并处理异常:
myURL1 = urllib.request.urlopen("https://www.runoob.com/")
print(myURL1.getcode())  # 200

try:
    myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html")
except urllib.error.HTTPError as e:
    if e.code == 404:
        print(404)  # 404

"""
urllib.parse 用于解析 URL,格式如下:
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
参数:
* urlstring 为 字符串的 url 地址,
* scheme 为协议类型,
* allow_fragments 参数为 false,则无法识别片段标识符。相反,它们被解析为路径,参数或查询组件的一部分,并 fragment 在返回值中设置为空字符串。

得到的url对象有这些属性:
1)scheme:URL协议,索引0
2)netloc:网络位置部分,索引1,如果值不存在则为空字符串
3)path:分层路径,索引2,如果值不存在则为空字符串
4)params:最后路径元素的参数,索引3,如果值不存在则为空字符串
5)query:查询组件,索引4,如果值不存在则为空字符串
6)fragment:片段识别,索引5,如果值不存在则为空字符串
7)username:用户名,如果值不存在则为None
8)password:密码,如果值不存在则为None
9)hostname:主机名(小写),如果值不存在则为None
10)port:端口号为整数(如果存在),如果值不存在则为None

"""
o = urllib.parse.urlparse("https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B")
print(o)

# 可以直接读取协议内容:
o = urllib.parse.urlparse("https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B")
print(o.scheme)

"""
urllib.robotparser 用于解析 robots.txt 文件。
robots.txt(统一小写)是一种存放于网站根目录下的 robots 协议,它通常用于告诉搜索引擎对网站的抓取规则。
urllib.robotparser 提供了 RobotFileParser 类,语法如下:
class urllib.robotparser.RobotFileParser(url='')

这个类提供了一些可以读取、解析 robots.txt 文件的方法:
1)set_url(url) - 设置 robots.txt 文件的 URL。
2)read() - 读取 robots.txt URL 并将其输入解析器。
3)parse(lines) - 解析行参数。
4)can_fetch(useragent, url) - 如果允许 useragent 按照被解析 robots.txt 文件中的规则来获取 url 则返回 True。
5)mtime() -返回最近一次获取 robots.txt 文件的时间。 这适用于需要定期检查 robots.txt 文件更新情况的长时间运行的网页爬虫。
6)modified() - 将最近一次获取 robots.txt 文件的时间设置为当前时间。
7)crawl_delay(useragent) -为指定的 useragent 从 robots.txt 返回 Crawl-delay 形参。 
如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。
8)request_rate(useragent) -以 named tuple RequestRate(requests, seconds) 的形式从 robots.txt 返回 Request-rate 形参的内容。 
如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。
9)site_maps() - 以 list() 的形式从 robots.txt 返回 Sitemap 形参的内容。 如果此形参不存在或者此形参的 robots.txt 条目存在语法错误,则返回 None。
"""
import urllib.robotparser

rp = urllib.robotparser.RobotFileParser()
rp.set_url("http://www.musi-cal.com/robots.txt")
print(rp.read())
rrate = rp.request_rate("*")
if rrate is not None:  # 判断对象是否存在
    print(rrate.requests)
    print(rrate.seconds)
print(rp.crawl_delay("*"))
print(rp.can_fetch("*", "http://www.musi-cal.com/cgi-bin/search?city=San+Francisco"))
print(rp.can_fetch("*", "http://www.musi-cal.com/"))

requests模块

Python 内置了 requests 模块,该模块主要用来发 送 HTTP 请求,requests 模块比 urllib模块更简洁。

# 导入 requests 包
import requests

# 发送请求
x = requests.get('https://www.runoob.com/')

# 返回网页内容
print(x.text)

每次调用 requests 请求之后,会返回一个 response 对象,该对象包含了具体的响应信息。

响应信息如下:

  • apparent_encoding    编码方式
  • close()    关闭与服务器的连接
  • content    返回响应的内容,以字节为单位
  • cookies    返回一个 CookieJar 对象,包含了从服务器发回的 cookie
  • elapsed    返回一个 timedelta 对象,包含了从发送请求到响应到达之间经过的时间量,可以用于测试响应速度。比如 r.elapsed.microseconds 表示响应到达需要多少微秒。
  • encoding    解码 r.text 的编码方式
  • headers    返回响应头,字典格式
  • history    返回包含请求历史的响应对象列表(url)
  • is_permanent_redirect    如果响应是永久重定向的 url,则返回 True,否则返回 False
  • is_redirect    如果响应被重定向,则返回 True,否则返回 False
  • iter_content()    迭代响应
  • iter_lines()    迭代响应的行
  • json()    返回结果的 JSON 对象 (结果需要以 JSON 格式编写的,否则会引发错误)
  • links    返回响应的解析头链接
  • next    返回重定向链中下一个请求的 PreparedRequest 对象
  • ok    检查 "status_code" 的值,如果小于400,则返回 True,如果不小于 400,则返回 False
  • raise_for_status()    如果发生错误,方法返回一个 HTTPError 对象
  • reason    响应状态的描述,比如 "Not Found" 或 "OK"
  • request    返回请求此响应的请求对象
  • status_code    返回 http 的状态码,比如 404 和 200(200 是 OK,404 是 Not Found)
  • text    返回响应的内容,unicode 类型数据
  • url    返回响应的 URL
 导入 requests 包
import requests

# 发送请求
x = requests.get('https://www.runoob.com/')

# 返回 http 的状态码
print(x.status_code)

# 响应状态的描述
print(x.reason)

# 返回编码
print(x.apparent_encoding)

requests 方法

requests 方法如下表:

  • delete(url, args)    发送 DELETE 请求到指定 url
  • get(url, params, args)    发送 GET 请求到指定 url
  • head(url, args)    发送 HEAD 请求到指定 url
  • patch(url, data, args)    发送 PATCH 请求到指定 url
  • post(url, data, json, args)    发送 POST 请求到指定 url
  • put(url, data, args)    发送 PUT 请求到指定 url
  • request(method, url, args)    向指定的 url 发送指定的请求方法

使用 requests.request() 发送 get 请求:

# 导入 requests 包
import requests

# 发送请求
x = requests.request('get', 'https://www.runoob.com/')

# 返回网页内容
print(x.status_code)

requests.request(method,url,**kwargs)

(1)method:请求方法,包含GET,HEAD,POST,PUT,PATCH,delete,OPTIONS这7种。

(2)**kwargs:是指能够加到url中的参数,是可选的,共13个访问控制参数。分别如下:

  • params:请求字典或者字节作为参数增加到url中。对URL进行修改。
  • data:字典,字节序列或文件对象。作为Request的内容。
  • json:JSON格式的数据,作为Request的内容。
  • headers:字典,HTTP定制头。
  • cookies:字典或CookiesJar,Requests中的cookies
  • auth:元组,支持HTTP认证功能。
  • files:字典类型,传输文件。向某个链接提交文件。
  • timeout:设定超时时间,秒为单位。如果在设定时间内请求内容没有返回回来,会出现timeout的异常。
  • proxies:字典类型,设定访问代理处理器,可以增加登录认证。可以有效隐藏用户爬取网页源的IP地址,防止对爬虫的逆追踪。
  • allow_redirects:一个开关。表示是否允许对URL进行重定向。
  • stream:一个开关。获取内容是否进行立即下载,默认情况是立即下载。
  • verify:认证SSL证书
  • cert:本地SSL证书路径。

requests.get(url,params=None,**kwargs)

  • params:请求字典或者字节作为参数增加到url中。对URL进行修改。
  • kwargs:request方法中除了params的其他12个访问控制参数。

requests.head(method,url,**kwargs)

  • kwargs有13个,与request相同。

requests.post(url,data=None,json=None,**kwargs)

  • **kwargs:除了data,json的其他11个控制访问参数。

requests.put(url,data=None,**kwargs)

  • **kwargs:除了data外的其他12个访问控制参数。

13个请求控制参数的使用

params:字典或字节序列,作为参数增加到url中

kv = {'key1':'value1','key2':'value2'}
r = requests.request('GET','http://www.baidu.com',params=kv)

data:字典、字节序列或文件对象,作为Request的对象

kv = {'key1':'value1','key2':'value2'}
r = requests.request('POST','http://www.baidu.com',data=kv)

json:JSON格式的数据,作为Request的内容

kv = {'key1':'value1','key2':'value2'}
r = requests.request('POST','http://www.baidu.com',json=kv)

headers:字典,HTTP定制头

hd = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36"}
r = requests.request('POST','http://www.baidu.com',headers=hd)

cookies:字典或CookieJar,Request中的cookie

auth:元组,支持HTTP认证功能

files:字典类型,传输文件

fs = {'file':open('data.xls','rb')}
r = requests.request('POST','http://www.baidu.com',files=fs)

timeout:设定超时时间,秒为单位

r = requests.request('GET','http://www.baidu.com',timeout=10)

timeout参数也可以传入一个包含两个简单浮点数的元组,用来分别设置请求超时时间和读取超时时间。

import requests

# 传入元组将分别作为连接,读取的超时时间
r = requests.get("https://baidu.com", timeout=(0.01, 0.01))
print(r.status_code)

proxies:字典类型,设置访问代理服务器,可以增加登录认证

pxs = {'http':'http://user:pass@10.10.10.1:1523'}
r = requests.request('GET','http://www.baidu.com',proxies=pxs)

allow_redirects:True/False,默认为Ture,重定向开关

stream:True/False,默认为True,获取内容立即下载开关

verify:True/False,默认为True,认证SSL证书开关

cert:本地SSL证书路径

6种常用的连接异常

requests.connectTimeout 与requests.Timeout区别是,前者是指连接这一单程时间超时。而后者指的是整个来回过程超时。

爬取网页通用框架:

请求会话

在很多时候我们开发的爬虫需要登录,登录后我们需要记录登录状态,否则无法爬取登录后才能爬取的网页,在request中提供了requests.Session()这样的类:

import requests
s = requests.Session()
s.get('http://httpbin.org/get')

这样我们的request只要调用一次登录入口就会自动维护网站的Session记录我们的登录状态,以后我们可以直接使用request访问登录才能访问的页面。

Cookie获取

我们可以使用cookies来获取响应中的cookie: 如果某个响应中包含一些 cookie,你可以快速访问它们:

req = requests.get("https://ptorch.com")

req = requests.get("https://ptorch.com")
print(req.cookies)
print(req.cookies['laravel_session'])

要想发送你的cookies到服务器,可以使用cookies参数:

cookies = dict(cookies_are='working Test')

req = requests.get("http://httpbin.org/cookies", cookies=cookies)
print(req.text)
# '{"cookies": {"cookies_are": "working Test"}}'

Cookie的返回对象为RequestsCookieJar,它的行为和字典类似,但界面更为完整,适合跨域名跨路径使用。你还可以把Cookie Jar传到Requests中:

jar = requests.cookies.RequestsCookieJar()
jar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
url = 'http://httpbin.org/cookies'
req = requests.get(url, cookies=jar)
print(req.text)
# '{"cookies": {"tasty_cookie": "yum"}}'

保存cookie方便下次访问,我们需要将CookieJar转为字典或者将字典转为CookieJar

#将CookieJar转为字典:
cookies = requests.utils.dict_from_cookiejar(r.cookies)

#将字典转为CookieJar:
ookies = requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)

下载图片

有时候我们想下载我们爬取页面的img图片,你可以使用requests请求图片,获取response.content文本信息,实际上获取的是图片的二进制文本,然后保存即可:

import requests

response = requests.get("https://ptorch.com/img/logo.png")
img = response.content
open('logo.jpg', 'wb').write(response.content)

如果要下载验证码,可以使用上面的会话请求加载这里的下载代码即可。

 

posted @ 2022-09-08 13:20  残城碎梦  阅读(416)  评论(0编辑  收藏  举报