python学习笔记(二)--高级部分

文章目录

  • 数据库
    • sqlite数据库
    • MySQL数据库
  • 窗口tkinter
      • 按钮
      • 图片
      • CheckButton
      • RadioButton
      • Entry输入框和Text多行文本框
      • ListBox
      • 菜单
      • 对话框
      • canvas画图
  • 爬虫
      • 添加头head,提交数据
      • 代理
      • 使用Beautiful Soup解析html和xml文件
      • 异常
  • socket编程
      • UDP 接收信息再回复信息
      • TCP 双向发送信息
  • 多线程
      • Condition对象实现PV操作
  • pillow图像处理


上篇基础部分: https://blog.csdn.net/wang342626/article/details/88904281


数据库

sqlite数据库

# 不用安装,自带模块
import sqlite3

# 创建连接对象,并且直接生成db文件,可用Navicat打开
connection = sqlite3.connect('D:/example.db')

# 执行sql语句
connection.execute("""create table student(sid int,name varchar(50) )""")
connection.execute("""insert into student values (1,'wang')""")
connection.execute("""insert into student values (?,?)""",('2','zhang'))  # 占位符

# 提交之后才能修改数据库
connection.commit()

# 查询语句
for row in connection.execute("""select * from student"""):
    print(row)

connection.close()

connection.rollback() 回滚

还可以使用cursor对象执行sql语句

import sqlite3

# 创建连接对象和cursor对象
connection = sqlite3.connect('D:/example.db')
cursor = connection.cursor()

# cursor执行sql语句
cursor.execute("""create table student(sid int,name varchar(50) )""")
cursor.execute("""insert into student values (1,'wang')""")
cursor.execute("""insert into student values (?,?)""",('2','zhang'))  # 占位符使用问号,不是%s

# 提交之后才能修改数据库
connection.commit()

# 查询语句
cursor.execute("""select * from student""")
res = cursor.fetchall()
for row in res:
    for col in row:
        print(col,end=' ')
    print('')

connection.close()

MySQL数据库

import pymysql

# 连接对象,必须要使用cursor执行sql语句
conn = pymysql.connect(host='localhost',port=3306,user='root',passwd='你的密码',db='data')
cursor =conn.cursor()

# 执行sql语句
cursor.execute(""" create table student(sid int,name varchar(50) )""")
num = cursor.execute("""insert into student values (1,'wang')""")
print(num)

# 格式化sql语句
sql = " insert into student values({},{}) ".format(1,'zhang')
print(sql)

num = cursor.execute(" insert into student values(%s,%s) ",(1,'zhang') )  # 占位符一律用%s,不用%d,也不用问号
print(num)

num = cursor.executemany("insert into student values (%s,%s)",[(3,'lisi'),(4,'xiaoming')]) #多个插入语句,使用列表
print(num)

conn.commit()


# 执行查询
res = cursor.execute("select * from student")
one = cursor.fetchone()
print(one)
many = cursor.fetchmany(2) #获取前2个结果
print(many)
all = cursor.fetchall() #获取剩下的所有结果
print(all)

conn.close()

窗口tkinter

更多详细教程: https://blog.csdn.net/jacky_zhuyuanlu/article/details/77475635

import tkinter as tk

# 生成顶层窗口root
root = tk.Tk()
root.title("这是标题")

# 生成一个标签
lablel = tk.Label(root,text="标签1")
lablel.pack()

# 显示窗口
root.mainloop()

设置文字左对齐, 文字左边距10
label = tk.Label(root,text="标签",justify=tk.LEFT,padx=10)

调整显示位置(上下左右), 调整边距
label.pack(side=tk.RIGHT,padx=10,pady=10)

按钮

import tkinter as tk

def fun1():
    print("按钮点击了,这是函数1")

# 顶层窗口root
root = tk.Tk()
root.title("这是标题")

# 按钮,点击事件使用cammand调用函数fun1
btn = tk.Button(root,text="打招呼",fg="blue",command=fun1)
btn.pack()

root.mainloop()

点击按钮修改标签文字

import tkinter as tk

def fun1():
    var.set("修改文字")

# 顶层窗口root
root = tk.Tk()
root.title("这是标题")

# 标签
var = tk.StringVar() # 修改的文字变量
var.set("标签的文字")
label = tk.Label(root,textvariable=var)
label.pack()

# 按钮,点击调用函数fun1
btn = tk.Button(root,text="修改标签的文字",fg="blue",command=fun1)
btn.pack()

root.mainloop()

图片

初始化加载图片 (仅支持gif,其他格式会报错couldn't recognize data in image file "D://1.jpg")

import tkinter as tk

# 顶层窗口root
root = tk.Tk()
root.title("标题")

# 图片包含在label里
img = tk.PhotoImage(file="D://1.gif") #只支持gif
label = tk.Label(root,image=img)
label.pack(side=tk.LEFT)

root.mainloop()

点击按钮加载图片 (仅支持gif,其他格式会报错couldn't recognize data in image file "D://1.jpg")

import tkinter as tk
import tkinter.filedialog

def choosepic():
    path =tk.filedialog.askopenfilename()
    varPath.set(path)

    # 动态给label设置图片,仅限于gif格式图片
    img_gif = tk.PhotoImage(file=path)  # file=不能少
    l1.config(image=img_gif)
    l1.image=img_gif



root = tk.Tk()
root.geometry('200x300')  # 不能限定窗口大小

varPath = tk.StringVar()
btn = tk.Button(root, text='选择图片', command=choosepic).pack() #点击按钮,选择图片
e1 = tk.Entry(root, state='readonly', text=varPath)
e1.pack()

# 图片预览标签
l1 = tk.Label(root)
l1.pack()

root.mainloop()

点击按钮加载图片 (支持所有格式图片)

import tkinter as tk
import tkinter.filedialog

from PIL import Image,ImageTk

def choosepic():
    path =tk.filedialog.askopenfilename()
    varPath.set(path)

    # 动态给label设置图片,支持所有格式图片
    img_open = Image.open(path)  # 需要导入 PIL中的Image
    imgTk = ImageTk.PhotoImage(img_open) #需要导入PIL中的ImageTk
    l1.config(image=imgTk)
    l1.image=imgTk


root = tk.Tk()
root.geometry('500x400')  # 不能限定窗口大小

varPath = tk.StringVar()
btn = tk.Button(root, text='选择图片', command=choosepic).pack() #点击按钮,选择图片
e1 = tk.Entry(root, state='readonly', text=varPath)
e1.pack()

# 图片预览标签
l1 = tk.Label(root)
l1.pack()

root.mainloop()

图片和文字混入,效果图:

python学习笔记(二)--高级部分_第1张图片
代码:

import tkinter as tk

# 顶层窗口root
root = tk.Tk()
root.title("标题")

# 图片包含在label里
img = tk.PhotoImage(file="D://1.gif")
label = tk.Label(root,
                 text="这是文字",
                 font=("微软雅黑",14),
                 justify=tk.LEFT,
                 image=img,
                 compound=tk.CENTER,
                 fg="white")
label.pack(side=tk.LEFT)

root.mainloop()

CheckButton

from tkinter import *

root = Tk()
root.title("窗口的标题")

# CheckButton的值,0表示未选,1表示选中
value = IntVar()
c = Checkbutton(root,text="勾选按钮",variable=value)
c.pack()

l = Label(root,textvariable=value) # 显示value的值
l.pack()

mainloop()

效果图:
python学习笔记(二)--高级部分_第2张图片

循环添加多个

from tkinter import *


root = Tk()
root.title("窗口的标题")

strings = ['打篮球','听音乐','跳舞']
v=[]

for s in strings:
    v.append(IntVar()) #添加变量到最后一个
    b = Checkbutton(root,text=s,variable=v[-1]) #v[-1]表示最后一个
    b.pack()

mainloop()

RadioButton

from tkinter import *


root = Tk()
root.title("窗口的标题")

v = IntVar()
# 显示在West方向
Radiobutton(root,text="男",variable=v,value=1).pack(anchor=W)
Radiobutton(root,text="女",variable=v,value=2).pack(anchor=W)

mainloop()

后面不写了,更多详细教程: https://blog.csdn.net/jacky_zhuyuanlu/article/details/77475635

Entry输入框和Text多行文本框

见教程: https://blog.csdn.net/jacky_zhuyuanlu/article/details/77475635

import tkinter as tk

window = tk.Tk()
window.title("biaoti")

# 单行输入框
username = tk.StringVar()
entryName = tk.Entry(window, width=80, textvariable=username)
entryName.pack()

# 密码框
password = tk.StringVar()
entryPswd = tk.Entry(window, show="*", width=80, textvariable=password)
entryPswd.pack()

# 多行文本框
text = tk.Text(window, width=30, height=3)  # 不需要textvariable=varName
text.place(x=100, y=100, width=100, height=50) 

window.mainloop()
# 多行文本框不需要 textvariable=varName
# 多行文本框插入字符的方法:
text.delete(0.0,tk.END) #清空内容 0.0是lineNumber.colNumber的表示方法
text.insert(tk.INSERT,"你好\n欢迎你") #添加文字

# 多行文本框获取字符的方法:
string = txtResult.get(0.0,tk.END)

#单行文本框设置和获取字符的方法:
varName.set()
varName.get()

# 修改文字大小
entry1=tk.Entry(window,show=None,font="Helvetica 20")

ListBox

教程 https://blog.csdn.net/jacky_zhuyuanlu/article/details/77475635 有一点点错
修改后的代码:

import tkinter as tk        
window=tk.Tk()
window.title('zhuyuanlu-jacky')
window.geometry('300x300') 

var1=tk.StringVar()
l=tk.Label(window,bg='yellow',width=4,textvariable=var1)
l.pack()
#光标在listbox上,把内容显示到label上
def print_selection():
    value=lb.get(lb.curselection())      #先要获得光标中我要显示的值
    var1.set(value)                           #再把值附在label当中

b1=tk.Button(window,text="print selection",width=15,height=2,command=print_selection)
b1.pack()

var2=tk.StringVar()
var2.set((11,22,'jacky','haerbin'))
lb=tk.Listbox(window,listvar=var2)

#如何插入元素进列表
list_items=['aa','bb','cc']      #先定义它是个列表
for item in list_items:
    lb.insert(tk.END,item)
lb.insert(1,'first')    #也可以按照索引插入
lb.pack()
window.mainloop()

菜单

import tkinter as tk

# 按钮的函数
def fun1():
    print("Test")


window=tk.Tk()

# 创建菜单
menuBar = tk.Menu(window)
window.config(menu=menuBar) #将菜单关联到窗口上

#添加文件菜单
fileMenu = tk.Menu(menuBar,tearoff=0) #tearoff=1或0是定义menu能不能被分开
menuBar.add_cascade(label='文件',menu=fileMenu) #文件菜单关联到menuBar上

# 文件菜单添加子项目
fileMenu.add_command(label='新建',command=fun1) #文件菜单下面添加按钮
fileMenu.add_command(label='打开',command=fun1)
fileMenu.add_command(label='保存',command=fun1)
fileMenu.add_separator()  #添加分割线
fileMenu.add_command(label='退出',command=window.quit)


window.mainloop()

对话框

是否取消对话框

import tkinter as tk
import tkinter.messagebox # 一定要导入这句话,否则会报错

res = tk.messagebox.askyesnocancel(title='是否保存?',message='是否保存?')
if(res==tk.YES):
    print("Yes")
elif(res==tk.NO):
    print("No")
elif(res==None):
    print("None")

canvas画图

import tkinter as tk

app = tk.Tk()
app.title('上下左右控制移动,鼠标点击向右运动,右击停止')
app['width']=800
app['height']=600

# 创建画布,并绑定事件
image = tk.PhotoImage(file='D:/1.gif')
canvas = tk.Canvas(app,bg='white',width=800,height=600)  #父亲的容器是app窗口
canvas.create_image(100,100,image=image)

canvas.pack(fill=tk.BOTH,expand=tk.YES) # canvas填充屏幕
canvas.focus() #canvas聚焦按键

# 画直线
canvas.create_line(10,10,10,500,fill='yellow')
canvas.create_line(20,20,20,600,dash=(4,4))  # 虚线

# 画矩形
lastDrawId = canvas.create_rectangle(10,10,100,200,fill=None, outline='black')  #记录上次画的矩形id

app.mainloop()

更多tkinter的案例:
https://blog.csdn.net/wang342626/article/details/90731106

爬虫

模块urllib包含4个部分: request, response, parse, error
python学习笔记(二)--高级部分_第3张图片

import urllib.request

# 下载html源代码
response = urllib.request.urlopen("http://www.baidu.com/")
html = response.read()
html.decode("utf8")
print(html)

# 下载二进制的图片等其他文件
response = urllib.request.urlopen("http://placekitten.com/g/200/300")
catImg = response.read()
with open("D://1.jpg",'wb') as file:
    file.write(catImg)
print("下载了一张猫的图片")

保存图片等网页文件还有更加简单的方法

urllib.request.urlretrieve(srcUrl,localPath)

另外: urlopen给的参数可以是request对象

# 这里的urlopen给的参数可以是request对象
requst = urllib.request.Request("http://placekitten.com/g/200/300")
print(type(requst))
response = urllib.request.urlopen(requst) #这里的urlopen给的参数可以是request对象

添加头head,提交数据

# 举例有道翻译
url="http://fanyi.youdao.com/translate?smartresult=dict&smartresult=rule"
# 注意有道反爬虫机制,url不是下面这个
# url='http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'

head={}
head['Referer']='http://www.youdao.com/'
head['User-Agent']='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3650.400 QQBrowser/10.4.3341.400'

data={}
data['type']='AUTO'
data['i']="这里填写你想要翻译的字符串"
data['doctype']='json'
data['xmlVersion']='1.6'
data['keyform']='fanyi.web'
data['ue']='UTF-8'
data['typoResult']='true'
data = urllib.parse.urlencode(data).encode('utf-8')

# 请求时发送数据data和添加头head,修改了User-Agent
request = urllib.request.Request(url,data,head)
response = urllib.request.urlopen(request)

html = response.read().decode('utf-8')
print(html)

# 解析json数据
dict1 = json.loads(html)
print(dict1)
result = dict1['translateResult'][0][0]['tgt']
print(result)

也可以稍后再添加头head

url='网址'
data={} #...

request = urllib.request.Request(url,data)
# 也可以稍后再添加头head,修改了User-Agent
request.add_header('Referer','http://www.youdao.com/')
request.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3650.400 QQBrowser/10.4.3341.400')

response = urllib.request.urlopen(request)

html = response.read().decode('utf-8')
print(html)

代理

import urllib.request

#安装代理
# 这里填写需要代理的ip地址,可能是无效的ip地址
proxy_support = urllib.request.ProxyHandler({'http':'120.198.230.15:8080'})
opener = urllib.request.build_opener(proxy_support)
opener.addheaders = [('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3650.400 QQBrowser/10.4.3341.400')]
urllib.request.install_opener(opener)

# 继续访问其他的url地址
url='http://www.whatismyip.com' # 查询本机ip的网站
response = urllib.request.urlopen(url)

使用Beautiful Soup解析html和xml文件

from bs4 import BeautifulSoup

url = 'http://www.ifanr.com/1179442'
response = urllib.request.urlopen(url)
htmlFile = response.read().decode('utf-8')

# 解析网页
soup = BeautifulSoup(htmlFile,"html.parser")
#按照class查找img标签,注意参数是class_还有个下划线
imgs = soup.find_all(name='img',class_='alignnone size-full')

# 获取标签img的某个属性
for img in imgs:
    src = img.attrs['src']
    print(src)

异常

urllib.error.HTTPError是urllib.error.URLError的子类,捕获HTTPError必须在前,如下所示:

import urllib.request
import urllib.error

req = urllib.request.Request('http://www/fishc.com/demo.html')
try:
    urllib.request.urlopen(req)
except urllib.error.HTTPError as e:
    print("HTTPError错误码是:"+e.code)
except urllib.error.URLError as e:
    print("出现了URLError")
else:
    print("没有出错!")

socket编程

UDP 接收信息再回复信息

接收端代码:(一定要先运行接收端再运行发送端,否则报错)

import socket  #不需要安装

# 创建UDP
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  # SOCK_DGRAM表示UDP,SOCK_STREAM表示TCP
s.bind(('',5000))  # 参数是元组, 绑定ip地址和端口,空字符串表示本机的任何可用ip,接受5000端口发来信息

# 等待接受信息
data,addr = s.recvfrom(1024)
print("IP:{} 端口:{}  发来信息:".format(addr[0],addr[1]))
msg = data.decode()
print(msg)

# 回复一条信息
s.sendto("吃过了".encode(),addr)

s.close()

发送端代码:

import socket

# 创建UDP
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)  

# 发送信息,必须要使用msg.encode()来编码
msg = '你吃过饭了吗?'
s.sendto(msg.encode(),("localhost",5000))

# 接受回复信息
data = s.recv(1024)
print(data.decode())

s.close()

TCP 双向发送信息

服务端代码:(先运行服务端,再运行客户端,否则报错)

import socket  # 不需要安装

# 创建TCP socket,绑定端口
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  # SOCK_STREAM表示TCP,SOCK_DGRAM表示UDP
s.bind(('',6000))  # 参数是元组, 绑定ip地址和端口,空字符串表示本机的任何可用ip,接受5000端口发来信息

# 监听1个客户端来连接我
print("正在等待客户端发起连接...")
s.listen(1)
conn,addr = s.accept()
print(addr,"已经连接上了!")


while True:
    # 服务端先接受信息
    data = conn.recv(1024)
    msg = data.decode()
    if msg=='quit': # 发来空消息就退出
        break
    print("收到信息:"+msg)
    # 再发送信息
    msg = input("输入你想发送的信息:")
    conn.sendall(msg.encode())
    if msg=='quit':
        break
conn.close()
s.close()

多线程

创建线程

import threading as th
import time

def func1(x,y):
    print(x,y)
    time.sleep(2)  # 单位是秒,不是毫秒
    print("完成")

# 创建线程,并传递参数
t1 = th.Thread(target=func1,args=(15,20))  # 直接调用函数,并且传递参数
t1.start()

创建线程类

import threading as th
import time


class myThread(th.Thread):  # 继承Thread对象,重写run方法
    def __init__(self,num,threadName):
        th.Thread.__init__(self,name=threadName)
        self.num = num

    def run(self):  # 重写run方法
        print("子线程正在运行中...")
        time.sleep(self.num)
        print("子线程运行完成")


t1 = myThread(2,'t1')
print(t1.daemon)  # 默认值为False,表示主线程结束前需要等待子线程
t1.daemon=True  # 修改为True,表示主线程结束时强制关闭子线程(一定要在开启线程之前修改)
t1.start()
print("主线程运行完成了!")
t1 = myThread(2,'t1')
t1.start()
print("主线程卡住了,等待子线程完成...")
t1.join()   # 表示阻塞当前线程,等待t1完成后才继续运行
print("主线程运行完成了!")

Condition对象实现PV操作

生产者和消费者算法

import threading as th
import time
from random import randint


# 生产者
class Producer(th.Thread):
    def __init__(self,threadName):
        th.Thread.__init__(self,name=threadName)
    def run(self):
        while True:
            # 获得锁
            condition.acquire()
            global lst
            if len(lst)==10:
                print("缓冲池满了,生产者正在等待中...")
                condition.wait()   # 调用这个方法将使该线程进入Condition对象的等待池中等待通知,并释放锁。使用前线程必须已获得锁定,否则将抛出异常
            else:
                x = randint(1,100)
                lst.append(x)
                print("生产了:",x,",并放入缓冲池中",lst)
                # 唤醒等待条件的线程
                time.sleep(0.5)
                condition.notify()  # 调用这个方法将从等待池中挑选一个线程并通知,收到通知的线程将自动调用acquire()尝试获得锁定并继续运行。调用这个方法不会释放锁定。使用前线程必须已获得锁定,否则将抛出异常
            # 释放锁
            condition.release()

# 消费者
class Consumer(th.Thread):
    def __init__(self,threadName):
        th.Thread.__init__(self,name=threadName)
    def run(self):
        while True:
            condition.acquire()
            global lst
            if len(lst)==0:
                print("缓冲池空,消费者等待中...")
                condition.wait()
            else:
                print("消费了:",lst.pop(0),",剩余:",lst)
                time.sleep(0.5)
                condition.notify()
            condition.release()


# 创建condition对象
condition = th.Condition()
lst=[]  # 假设列表最多只能容纳10个
p = Producer('生产者')
c = Consumer('消费者')
p.start()
c.start()
运行结果:
生产了: 23 ,并放入缓冲池中 [23]
生产了: 37 ,并放入缓冲池中 [23, 37]
生产了: 70 ,并放入缓冲池中 [23, 37, 70]
生产了: 83 ,并放入缓冲池中 [23, 37, 70, 83]
生产了: 4 ,并放入缓冲池中 [23, 37, 70, 83, 4]
生产了: 41 ,并放入缓冲池中 [23, 37, 70, 83, 4, 41]
消费了: 23 ,剩余: [37, 70, 83, 4, 41]
消费了: 37 ,剩余: [70, 83, 4, 41]
消费了: 70 ,剩余: [83, 4, 41]
消费了: 83 ,剩余: [4, 41]
消费了: 4 ,剩余: [41]
消费了: 41 ,剩余: []
缓冲池空,消费者等待中...
生产了: 63 ,并放入缓冲池中 [63]
生产了: 4 ,并放入缓冲池中 [63, 4]
生产了: 88 ,并放入缓冲池中 [63, 4, 88]

pillow图像处理


from PIL import Image

# 打开图片
im = Image.open("D:/1.jpg")  # type: Image.Image   # 制定类型,便于pyCharm代码提示
# 打开查看
# img.show()


# 大小
print(im.size)  # (65, 65)
print(im.width)
print(im.height)

# 格式
print(im.format)  # 'GIF'
# 查看图像直方图
# print(im.histogram())


# 查看坐标的像素值
color = im.getpixel((10,10))  # 参数是元组类型的坐标xy,返回RGB值元组类型,如果是256色图比如gif,就返回一个值
print(color)
# 设置像素值
im.putpixel((10,10),(255,255,255))  # 设置坐标(10,10)的RGB值,如果是256色图,第二个参数只需要一个值


# 保存图片
im.save("D:/2.jpg")
im.save("D:/2.gif")  #也可以格式转换


# 图像缩放
im.resize((100,100))
# 旋转
im.rotate(90)  # 逆时针90度
# im.transpote(Image.ROTATE_180)  # 逆时针180度
# im.transpote(Image.FLIP_LEFT_RIGHT)  #水平翻转
# im.transpote(Image.FLIP_TOP_BOTTOM)  #垂直翻转


# 裁剪
box=(5,5,10,10)
#  box=(x,y,x+w,y+h)  # 左上角坐标和右下角坐标,也可以用x+w,y+h计算出来
region = im.crop(box)  # 裁剪
im.paste(region,box)  # 粘贴
im.show()

图像调整

from PIL import Image, ImageFilter
from PIL import ImageGrab


# 屏幕截图
# box = (x,y,x+w,y+h)
box = (100,100,200,200)
im = ImageGrab.grab(box)
im = ImageGrab.grab()  # 不带参数表示全屏截图
im.show()


# 图像模糊
im = im.filter(ImageFilter.BLUR)
im = im.filter(ImageFilter.GaussianBlur)  # 高斯模糊
im = im.filter(ImageFilter.MedianFilter)  # 中值模糊
# 图像边缘提取
# im = im.filter(ImageFilter.FIND_EDGES)

# 对比度
im = ImageEnhance.Contrast(im)
im = im.enhance(1.3)  # 对比度增加1.3

# 图像点运算
im = im.point(lambda i: i*1.3)  # 整体变亮
im = im.point(lambda i: i*0.7)  # 整体变暗


# 图像颜色调整
r,g,b = im.split()  # 分离图像
r = r.point(lambda i: i*1.3)  # 红色分量变成1.3倍
g = g.point(lambda i: i*0.9)  # 绿色分量变成0.9倍
b = b.point(lambda i: 0)  # 蓝色分量变成0
im = Image.merge(im.mode,(r,g,b))  # 图像合并

你可能感兴趣的:(Python,学习笔记)