属性、正则表达式、pymysql、多线程编程
昨天回顾
-
生成器
- 生成器函数
- 生成器表达式
-
面向对象编程
-
class 语句
class Dog: def __init__(self, *args, **kwargs): '创建一些所有对象共有的属性' self.foods = [] self.total_sleep_time = 0 # .... def eat(self, food): pass def sleep(self, hour): pass
-
继承
class SuperDog(Dog): def train(self, hour): '导盲犬的驯练' pass def eat(self, food): print('xxxx')
-
属性
-
模块内的
__name__
属性如果 一个模块是主模块,则
__name__
绑定'__main__'
如果 一个模块不是主模块,则
__name__
绑定文件名 -
super() 函数
-
作用
显示的调用被覆盖的父类方法
-
示例
-
class A:
def say_hello(self):
print('Hello A')
class B(A):
def say_hello(self):
print("hello B")
# self.say_hello() 无限递归调用
# 能否在此方法内调用 A类里面的 say_hello()
# 方法1
# A.say_hello(self)
# 方法2 ,super() 会把self 看成是A类的对象
super().say_hello()
b = B()
b.say_hello() # hello B Hello A
正则表达式 (regular express)
正则表达式是表示 文字的排列规则的一个字符串, 使用来匹配文字的匹配模式.
-
作用
用于文字的定位,搜索和内容的提取
元字符
类别 | 元字符 |
---|---|
匹配字符 |
. (不包含\n ) [...] [^...] \d \D \w \W \s \S |
匹配重复 |
* + ? {n} {m,n}
|
匹配位置 | ^ $ \b \B |
其他 | ` |
-
示例
# 标识符 的正则表达式 [A-Za-z_][A-Za-z_0-9]* a* -> '' 'a' 'aaaaa' a+ -> 'a' 'aaaaaa' [ab]+ --> 'a' 'b' 'abaaabbb' [ab]{3} --> 'aaa' 'bbb' 'aba' [ab]{3,5}--> 'aaa' 'aaaaa' 'aabb' # 匹配 .mp3 文件 '\w\.mp3/pre>---> 'abc.mp3' '(\w\.mp3$)|(\w\.MP3$)' 'abc.mp3' 'abc.MP3' '\w\.[mM][pP]3' 'abc.mP3' 'abc.mp3' 'abc.MP3'
-
re 模块
import re
-
方法
re.findall('正则表达式', '要匹配的字符串')
返回成功匹配的字符串的列表
-
-
示例
>>> import re >>> s = 'ABC123abcd456 13888888899' >>> re.findall('\d{3}', s) ['123', '456', '138', '888', '888'] >>> re.findall('1[357][0-9]{9}', s) ['13888888899']
-
普通字符
'ab' # 普通字符 只匹配'ab'
>>> import re # 导入正则表表达式模块 >>> s = 'abcdeabca' >>> re.findall('ab', s) ['ab', 'ab']
-
或关系
| 匹配两侧任意的正则表达式
>>> import re # 导入正则表表达式模块 >>> s = 'abcdeabca' >>> re.findall('ab|de', s) ['ab', 'de', 'ab']
-
匹配单个字符串
. 匹配除换行符 以外的任意的一个字符
>>> import re >>> re.findall('张.丰', '张三丰,张四丰,张老师') ['张三丰','张四丰']
-
匹配字符集
[字符集] 匹配其中的一个字符
>>> import re >>> s = 'How are you!' >>> re.findall('[aeiou]', s) ['o', 'a', 'e', 'o', 'u'] >>> re.findall('[0-9A-Za-z]', 'A$%^^%b!#$@!#$0') ['A', 'b','0']
^ 匹配目标字符的开始位置
$ 匹配目标字符的结束位置>>> re.findall('^hello', 'hello world') ['hello'] >>> re.findall('^hello', 'a hello world') [] >>> re.findall('world/pre>, 'hello world') ['world']
* 匹配前面的字符出现 0 或多次
+ 匹配前面的字符出现 1 或多次
? 匹配前面的字符出现 0 或1次>>> re.findall('wo*', 'wooooooo~~w! woo') ['wooooooo', 'woo'] >>> re.findall('[A-Z][a-z]+', 'Hello World abcd') ['Hello','World'] >>> re.findall('-?[0-9]+', 'name: Jame, age: 18, money:-100') ['18', '-100']
{n} # 前面的字符出现n 次
{m,n} # 前面的字符出现m到n次>>> re.findall('[0-9]{3}', '888 9999 1000000') ['888', '999', '100', '000'] >>> re.findall('[0-9]{4,10}', '888 9999 1000000') ['9999', '1000000']
\d 匹配任意的数字 [0-9]
\D 匹配任意的非数字>>> re.findall('\d{1,5}', 'MySql: 3306, http:80') ['3306', '80']
\w 匹配普通字符
\W 匹配非普通字符
普通字符是指 数字,字母,下划线,汉字>>> re.findall('\w+', 'MySql: 3306, http:80') ['MySql', '3306', 'http', '80']
\s 匹配空字符
\S 匹配非空字符
空字符是指 '\r' '\n' '\t' '\v' '\f'>>> re.findall('\w+\s+\w+', 'hello world') ['hello world']
\b 表示单词的边界
\B 表示非单词的边界>>> re.findall(r'\bis\b', 'This is a test') ['is']
>>> s = '''SERVER = 192.168.9.102 PORT = 80 SERVERNAME = GAME1 REMOTE = 188.3.69.888 ''' >>> server_re = r'SERVER\s*=\s*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' server_ip = re.findall(server_re, s) >>> server_re = r'SERVER\s*=\s*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' >>> server_ip = re.findall(server_re, s) >>> server_ip
['SERVER = 192.168.9.102']
>>> ip_list = re.findall(r'[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}', server_ip[0]) print("SERVER=", ip_list[0])
安装python 的包
python 有很多的第三方软件包, 提供了 标准库中没有的功能.
python 的官方支持的软件包的网站: https://pypi.org
- 安装方法
在Redhat 或 cent OS 上 yum 用于安装 rpm 包
Python 使用 pip3 命令(Windows 上用pip命令) 来安装 Python 的包
在线安装 python 的包
打开一个终端
pip3 install 包名
-
示例
pip3 install wget # 或者 pip3 install pymysql
-
解决错误的方法
-
更新 pip3
pip3 install --upgrade pip # 或者 python3 -m pip install -U pip
-
-
更换国内的pip 源
# 在用户主目录下创建一个文件夹 .pip mkdir ~/.pip # 在 ~/.pip/文件夹下创建一个文件 'pip.conf' vim ~/.pip/pip.conf # 写入如下内容 [global] index-url=http://mirrors.aliyun.com/pypi/simple/ [install] trusted-host=mirrors.aliyun.com
也可以百度搜寻其他的源
-
在使用 pip3 命令时手动指定源
pip3 install -i 源的地址 模块名
示例
pip3 install -i http://mirrors.aliyun.com/pypi/simple/ wget pip3 install -i http://mirrors.aliyun.com/pypi/simple/ pymysql
离线安装 python 的包
- 方式一 : 安装 .whl 的包
# 先下载 XlsxWriter-1.3.8-py2.py3-none-any.whl
pip3 install XlsxWriter-1.3.8-py2.py3-none-any.whl
pip3 install pymysql........whl
- 方式二: 安装压缩包类型的python 包
# 先下载 XlsxWriter-1.3.8.tar.gz 压缩文件格式的包
tar -xzvf XlsxWriter-1.3.8.tar.gz
cd XlsxWriter-1.3.8 # 进入解压缩后的文件夹
python3 setup.py install # 用 python3 运行setup.py 来安装
pymysql 应用
-
安装 mysql-server 或 mariadb-server
# 安装 mariadb yum install mariadb-server # 启动 mariadb 服务 systemctl start mariadb # systemctl restart mariadb systemctl enable maridb # 修改管理员账号的密码为 tedu.cn mysqladmin password tedu.cn # 用 mysql 客户端来登录数据库 mysql -uroot -ptedu.cn
创建一个 nsd21xx 的数据库
MariaDB [(none)]> CREATE DATABASE nsd21xx DEFAULT CHARSET utf8;
Query OK, 1 row affected (0.000 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| nsd21xx |
| performance_schema |
+--------------------+
4 rows in set (0.000 sec)
- 安装 pymysql 包
pip3 install pymysql
- 下午上课前做的准备工作:
- 成功安装mysql 数据库或者mariadb 数据库(二选一)
- 安装pymysql python 的第三方包
用 pymysql 模块来操作数据库
- 用 pymysql 创建数据表
见: pymysql_create_table.py
- 源代码
file: pymysql_create_table.py
# 导入 pymysql 包
import pymysql
# 连接数据库
conn = pymysql.connect(
host='localhost',
user='root',
password='tedu.cn',
db='nsd21xx', # 指定操作哪一个数据库
charset='utf8' # 指定操作的字符集
)
# 操作数据库
# 需要使用 游标来操作数据库
cursor = conn.cursor() # 创建游标
# 制定要操作的 SQL 语句
create_dep = '''CREATE TABLE departments(
id INT,
dep_name VARCHAR (20),
PRIMARY KEY(id)
)'''
# 使用游标 来执行 SQL 语句
cursor.execute(create_dep) # 写入 SQL 语句
conn.commit() # 提交SQL 语句到 服务器去执行
# 如果不再执行SQL 语句则 需要关闭游标
cursor.close()
# 操作完数据库,断开连接
conn.close() # > quit;
结果
[root@localhost ~]# mysql -uroot -ptedu.cn
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 17
Server version: 10.3.27-MariaDB MariaDB Server
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> use nsd21xx;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [nsd21xx]> show tables;
Empty set (0.000 sec)
MariaDB [nsd21xx]> show tables;
+-------------------+
| Tables_in_nsd21xx |
+-------------------+
| departments |
+-------------------+
1 row in set (0.000 sec)
MariaDB [nsd21xx]> desc departments;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| dep_name | varchar(20) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
2 rows in set (0.001 sec)
- 用pymysql 模块实现对 mysql数据库的增删改查
此示例示意 数据库的增删改查操
file: pymysql_create_table.py
1. 增加数据
# 导入 pymysql 包
import pymysql
# 连接数据库
conn = pymysql.connect(
host='localhost',
user='root',
password='tedu.cn', # 密码以实际情况为主
db='nsd21xx', # 指定操作哪一个数据库
charset='utf8' # 指定操作的字符集
)
# 操作数据库
# 需要使用 游标来操作数据库
cursor = conn.cursor() # 创建游标
# 在此处写SQL语句 进行增删改查操作
# 1\. 插入数据
insert_sql = 'INSERT INTO departments VALUES (%s, %s)'
# # 1.1 插入一条数据到表 departments
cursor.execute(insert_sql, (1, '人事部'))
# # 1.2 插入多行数据, 用 executemany 方法 第二个参数是 列表
cursor.executemany(insert_sql, [
(2, '运维部'),
(3, '开发部'),
(4, '测试部'),
(5, '财务部'),
])
conn.commit() # 把SQL 语句提交到服务器
2. 查询数据
# 导入 pymysql 包
import pymysql
conn = pymysql.connect(
host='localhost',
user='root',
password='tedu.cn', # 密码
db='nsd21xx', # 指定操作哪一个数据库
charset='utf8' # 指定操作的字符集
)
# 操作数据库
# 需要使用 游标来操作数据库
cursor = conn.cursor() # 创建游标
select_sql = 'SELECT id, dep_name FROM departments'
cursor.execute(select_sql)
# 2.1 取出一行数据
result1 = cursor.fetchone()
print(result1)
# 2.2 取出2行数据
result2 = cursor.fetchmany(2)
print(result2)
# 2.3 取出剩余的全部数据
result3 = cursor.fetchall()
print(result3)
3. 修改数据
# 导入 pymysql 包
import pymysql
conn = pymysql.connect(
host='localhost',
user='root',
password='tedu.cn', # 密码
db='nsd21xx', # 指定操作哪一个数据库
charset='utf8' # 指定操作的字符集
)
# 操作数据库
# 需要使用 游标来操作数据库
cursor = conn.cursor() # 创建游标
update_sql = 'UPDATE departments SET dep_name=%s WHERE dep_name=%s'
cursor.execute(update_sql, ('人力资源部', '人事部'))
conn.commit() # 提交
4. 删除数据
# 导入 pymysql 包
import pymysql
conn = pymysql.connect(
host='localhost',
user='root',
password='tedu.cn', # 密码
db='nsd21xx', # 指定操作哪一个数据库
charset='utf8' # 指定操作的字符集
)
# 操作数据库
# 需要使用 游标来操作数据库
cursor = conn.cursor() # 创建游标
delete_sql = 'DELETE FROM departments WHERE id=%s'
r = cursor.execute(delete_sql, (5,))
conn.commit()
如果不再执行SQL 语句则 需要关闭游标(末尾添加)
cursor.close()
操作完数据库,断开连接(末尾添加)
conn.close() # > quit;
subprocess 模块
用此模块可以执行系统命令
文档: https://docs.python.org/zh-cn/3/library/subprocess.html
-
示例
# 导入模块 import subprocess # shell=True, 指明此命令在 shell 环境下执行 # stdout=subprocess.PIPE 指明标准输出保存到 stdout 属性中 result = subprocess.run('ls ~', shell=True, stdout=subprocess.PIPE) print('刚才您输入的命令是:', result.args) # 执行的命令 'ls ~' print('此程序运行的返回值是:', result.returncode) # 即 $? # result.stdout绑定的是 ls ~ 打印在屏幕上的数据的字节串 print('此程序的标准输出是:', result.stdout.decode()) # 执行一个命令,此命令会产生错误 r = subprocess.run('ls ~/abcdefg', # ~/abcdefg 文件不存在 shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) print("ls ~/abcdefg 命令执行的返回值是:", r.returncode) # 2 print("ls ~/abcdefg 命令执行的标准输出是:", r.stdout) # b'' print("ls ~/abcdefg 命令执行的标准错误输出是:", r.stderr.decode()) # 'ls: 无法访问'/root/abcdefg': 没有那个文件或目录'
-
示例2
写一个程序,测试此网络内, 192.168.1.1 ~ 192.168.1.254 之间的机器,哪些开机,哪些关机 import subprocess r = subprocess.run('ping -c2 192.168.1.1 &> /dev/null', shell=True) if r.returncode == 0: print('192.168.1.1 通') else: print('192.168.1.1 不通')
答案
# 写一个程序,测试此网络内,
# 192.168.1.1 ~ 192.168.1.254 之间的机器,
# 哪些开机,哪些关机
import subprocess
# r = subprocess.run('ping -c2 192.168.1.1 &> /dev/null', shell=True)
# if r.returncode == 0:
# print('192.168.1.1 通')
# else:
# print('192.168.1.1 不通')
def ping(host_ip):
r = subprocess.run('ping -c2 %s &> /dev/null' % host_ip, shell=True)
if r.returncode == 0:
print(host_ip, ': up')
else:
print(host_ip, ': down')
if __name__ == '__main__':
# 生成 192.168.1.1 ~ 192.168.1.254 范围内的IP
for x in range(1, 255):
ipv4 = '192.168.1.%d' % x
# print("IP:", ipv4)
ping(ipv4)
多线程编程
一个进程可以有多个执行路径,通常可以每个执行路径分配在不同的CPU 上并行执行, 这种运行方式是多线程
文档:https://docs.python.org/zh-cn/3/library/threading.html
- 问题
如何能让下面的两个函数同时执行
import time
def say_hello():
for x in range(10):
print("hello!!!")
time.sleep(1)
def say_world():
for y in range(10):
print('world!!!')
time.sleep(1)
say_hello()
say_world()
使用多线程
- 创建线程对象的方法
import threading
# 用threading 的 Thread 类来创建一个线程对象
threading.Thread(target=None, args=(), kwargs={}, *, daemon=None)
-
示例
import threading import time def say_hello(): for x in range(10): print("hello!!!") time.sleep(1) # 用threading 的 Thread 类来创建一个线程对象 用 t 变量绑定 t = threading.Thread(target=say_hello) # 启动线程 # 用 Thread对象的start() 方法来启动线程,让 线程中 target 绑定的函数,异步执行 t.start()
-
完整示例
import threading # 导入多线程模块
import time
def say_hello():
for x in range(10):
print("hello!!!")
time.sleep(1)
def say_world():
for y in range(10):
print('world!!!')
time.sleep(1)
if __name__ == '__main__':
# 用多线程来并行
# 1\. 创建一个线程,绑定 say_hello 函数
t1 = threading.Thread(target=say_hello)
t1.start() # 启动 t1 线程
t2 = threading.Thread(target=say_world)
t2.start()
print("主线程运行结束")
# 串行
# say_hello()
# say_world()
paramiko 模块
此模块实现了 ssh 客户端的功能
ssh 命令 可以远程登录一台主机并远程操作这台主机
- 安装 paramiko
pip3 install paramiko
- 示例
# 导入 paramiko 模块
import paramiko
# 创建一个paramko 客户端对象
ssh_clint = paramiko.SSHClient()
# 设置自动接受服务器的主机密钥
ssh_clint.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 登陆远程主机
ssh_clint.connect('192.168.1.64', # 远程主机的IP
username='root', # 远程主机的用户名
password='root', # 远程主机的密码
port=22 # ssh 的端口号
)
# 在此处操作远程主机
result = ssh_clint.exec_command('id root; id zhangsan') # 在远程主机上执行命令
# print('len(result)=', len(result)) # result 绑定三个文件流对象的元组
stdout = result[1] # 得到标准输出
stderr = result[2] # 得到标准错误输出
print("标准输出:", stdout.read().decode())
print("标准错误输出:", stderr.read().decode())
ssh_clint.exec_command('mkdir 魏老师的专用文件夹')
# 关闭连接
ssh_clint.close() # 相当于在ssh 的内部执行 exit 命令