疯狂python讲义学习笔记——中十章完结
生活随笔
收集整理的這篇文章主要介紹了
疯狂python讲义学习笔记——中十章完结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
#第十一章 thinker
import tkinter as tk
print(help(tk.Button.__init__))#以按扭為例查看有什么屬性
class myApplication(tk.Frame):def __init__(self,master=None):#一、frametk.Frame.__init__(self,master)self.pack()#二、buttononButton=tk.Button(self)#創(chuàng)建一個(gè)按鈕下面是屬性設(shè)置默認(rèn)值onButton['activebackground']='gray25' #激活狀態(tài)背景色onButton['activeforeground']='gray25' #激活狀態(tài)前景色onButton['anchor']='center' #位于窗口位置,另有NW,SE等八選項(xiàng)onButton['background']='gray25' #正常狀態(tài)背景色gray25#onButton['bitmap']= #位圖暫時(shí)沒有onButton['borderwidth']=30 #邊框?qū)挾?#xff0c;單位是像素onButton['cursor']='gumby' #光標(biāo)形式gumby#onButton['command']= #鼠標(biāo)離開時(shí)觸發(fā)調(diào)用onButton['disabledforeground']='gray25'#禁用狀態(tài)前景色gray25onButton['font']='Helvetica' #字體onButton['foreground']='gray25' #正常狀態(tài)前景色onButton['highlightbackground']='gray' #高亮狀態(tài)背景色onButton['highlightcolor']='gray' #高亮狀態(tài)前景色onButton['highlightthickness']=2 #高亮狀態(tài)邊框?qū)挾萶nButton['height']=20 #以font字體字符高度為單位#onButton['image']= #按鈕圖像暫時(shí)未有 onButton['justify']='right' #組件內(nèi)部內(nèi)容對齊方式onButton['padx']=30 #組件水平方向留白o(hù)nButton['pady']=30 #組件豎直方向留白o(hù)nButton['relief']='raised' #組件3D效果#onButton['selectbackground']='gray' #選中時(shí)背景色#onButton['selectborderwidth']=2 #選中時(shí)3D邊框?qū)挾?onButton['selectforeground']='gray' #選中時(shí)前景色onButton['state']='normal' #組件當(dāng)前狀態(tài)NORMAL或DISABLE1onButton['takefocus']=1 #鍵盤接收焦點(diǎn)SHIFT+TAB,0則不接收onButton['text']='ok' #文本#onButton['textvariable']=bnText #變量名,獲取字符串onButton['underline']=2 #文本第幾字符加下劃線onButton['width']=20 #以font字體字符高度為單位onButton['wraplength']=20 #對支持換行的組件每行最大字符數(shù)#onButton['xscrollcommand']=scroll.set#onButton['yscrollcommand']=scroll.setonButton.pack()#三、Labelw=tk.Label(self)w.x=tk.PhotoImage(file='./image/background.png')w['image']=w.x w.pack()
app=myApplication()
app.master.title('CJ')
app.mainloop()#pack
from tkinter import *
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):fm1=Frame(self.master)# 創(chuàng)建第一個(gè)容器fm1.pack(side=LEFT,fill=BOTH,expand=YES)#該容器放在左邊排列Button(fm1,text='第一個(gè)').pack(side=TOP)#在frm1中設(shè)按鈕且不填充Button(fm1,text='第二個(gè)').pack(side=TOP,fill=X,expand=YES)#在frm1中設(shè)按鈕且在X方向填充(無效果)fm2=Frame(self.master)# 創(chuàng)建第二個(gè)容器fm2.pack(side=LEFT,padx=10,fill=BOTH,expand=YES)# 該容器放在左邊排列,就會挨著fm1Button(fm2, text='第一個(gè)').pack(side=RIGHT)## 設(shè)置按鈕從右邊開始排列,不填充Button(fm2, text='第二個(gè)').pack(side=RIGHT, fill=X, expand=YES)#X方向填充 Button(fm2, text='第三個(gè)').pack(side=RIGHT, fill=Y, expand=YES)#Y方向填充 fm3 = Frame(self.master)# 創(chuàng)建第三個(gè)容器fm3.pack(side=RIGHT, padx=10, fill=BOTH, expand=YES)# 該容器放在右邊排列Button(fm3, text='第一個(gè)').pack(side=BOTTOM, fill=Y, expand=YES)Button(fm3, text='第二個(gè)').pack(side=BOTTOM, fill=Y, expand=YES)Button(fm3, text='第三個(gè)').pack(side=BOTTOM, fill=Y, expand=YES)
root = Tk()
root.title("Pack布局")
display = App(root)
root.mainloop()#grid
from tkinter import *
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):Entry(relief=SUNKEN,font=('Courier New',24),width=25).pack(side=TOP, pady=10)#創(chuàng)建輸入組件放頂部p=Frame(self.master)#創(chuàng)建framep.pack(side=TOP)#放頂部names=("0","1","2","3","4","5","6","7","8","9","+","-","*","/",".","=")for i in range(len(names)):#遍歷字符串元組b=Button(p,text=names[i],font=('Verdana',20),width=6)#創(chuàng)建p的子對象Buttonb.grid(row=i//4,column=i%4)
root = Tk()
root.title("Grid布局")
App(root)
root.mainloop()#place
from tkinter import *
import random
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):books=('瘋狂Python講義','瘋狂Swift講義','瘋狂Kotlin講義','瘋狂Java講義','瘋狂Ruby講義')for i in range(len(books)):ct = [random.randrange(256) for x in range(3)] # 生成3個(gè)隨機(jī)數(shù)bg_color="#%02x%02x%02x" % tuple(ct)#得到背景色grayness=int(round(0.299*ct[0]+0.587*ct[1]+0.114*ct[2]))#得到灰度,下面用來設(shè)前景色lb=Label(root,text=books[i],fg='White' if grayness<120 else 'Black',bg=bg_color)lb.place(x=20,y=36+i*36,width=180,height=30) # 使用place()設(shè)置該Label的大小和位置
root = Tk()
root.title("Place布局")
root.geometry("250x250+30+30")#設(shè)置窗口的大小和位置width x height + x_offset + y_offset
App(root)
root.mainloop()#command
from tkinter import *
import random
class App:def __init__(self):self.master = Tk()self.initWidgets()self.master.title("簡單事件處理")self.master.mainloop()def initWidgets(self):self.label = Label(self.master, width=30)self.label['font'] = ('Courier', 20) #字體self.label['bg'] = 'white' #背景色self.label.pack()self.bn = Button(self.master, text='單擊我', command=self.change)self.bn.pack()def change(self):self.label['text'] = '歡迎學(xué)習(xí)Python'ct = [random.randrange(256) for x in range(3)]# 生成3個(gè)隨機(jī)數(shù)grayness = int(round(0.299*ct[0] + 0.587*ct[1] + 0.114*ct[2]))bg_color = "#%02x%02x%02x" % tuple(ct)#把三個(gè)隨機(jī)數(shù)轉(zhuǎn)成顏色格式self.label['bg'] = bg_colorself.label['fg'] = 'black' if grayness > 125 else 'white'
my_app=App()#bind
from tkinter import *
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):self.show = Label(self.master, width=30, bg='white', font=('times', 20))self.show.pack()self.bn = Button(self.master, text='CJ的按鈕')self.bn.pack(fill=BOTH, expand=YES)self.bn.bind('<Button-1>',self.one)self.bn.bind('<B2-Motion>',self.b2_motion)self.bn.bind('<Double-3>',self.double)self.bn.bind('<Motion>',self.motion)def one(self, event):self.show['text']="左鍵單擊:%s" % event.widget['text']def b2_motion(self,event):self.show['text']="你正在按著中鍵移動"def double(self, event):self.show.config(text="右鍵雙擊:%s" % event.widget['text'])def motion(self,event):self.show['text']="鼠標(biāo)坐標(biāo)更新為(%d %d)"%(event.x,event.y)
root = Tk()
root.title('簡單綁定')
App(root)
root.mainloop()#demo_calculator
from tkinter import *
class App:def __init__(self, master):self.master = masterself.initWidgets()self.flag = 0def initWidgets(self):self.show=Label(relief=SUNKEN,font=('Courier New',24),width=25,bg='white',anchor=E)self.show.pack(side=TOP, pady=10)self.p = Frame(self.master)self.p.pack(side=TOP)names=("0","1","2","3","4","5","6","7","8","9","+","-","*","/",".","=")for i in range(len(names)):b=Button(self.p,text=names[i],font=('Verdana',20),width=6)b.grid(row=i // 4, column=i % 4)b.bind('<Button-1>', self.click)def click(self, event):if(event.widget['text'] != '='):self.show['text'] = self.show['text'] + event.widget['text']self.flag = 0elif(event.widget['text']=='='):if(self.flag==1):self.show['text']=''else:self.flag=1#先設(shè)flag是為了下一行出錯(cuò)(如輸入01+2)方法直接返回時(shí)也能使用雙擊=消值功能self.show['text']=str(eval(self.show['text']))#使用eval函數(shù)計(jì)算表達(dá)式的值并顯示
root = Tk()
root.title("計(jì)算器")
App(root)
root.mainloop()#ttk(就是改了下裝飾)
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):cb=ttk.Combobox(self.master, font=24)#下拉列表cb['values'] = ('Python', 'Swift', 'Kotlin')cb.pack(side=LEFT, fill=X, expand=YES)lab = ttk.Label(self.master, text='我的標(biāo)簽', font=24)lab.pack(side=TOP, fill=BOTH, expand=YES)bn = ttk.Button(self.master, text='我的按鈕')bn.pack()
root = Tk()
root.title("簡單事件處理")
App(root)
root.mainloop()#StringVar(IntVar/DoubleVar/BooleanVar)
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
import random
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):self.st = StringVar()#這個(gè)變量的獲取與調(diào)用就是用get,set,注意下面的輸入框的內(nèi)從與這個(gè)變量綁定ttk.Entry(self.master,textvariable=self.st,width=24,font=('StSong',20,'bold'),foreground='red').pack(fill=BOTH, expand=YES)f = Frame(self.master)f.pack()ttk.Button(f,text='改變',command=self.change).pack(side=LEFT)ttk.Button(f,text='獲取',command=self.get).pack(side=LEFT)def change(self):books = ('瘋狂Python講義', '瘋狂Kotlin講義', '瘋狂Swift講義')self.st.set(books[random.randint(0, 2)])def get(self):messagebox.showinfo(title='輸入內(nèi)容', message=self.st.get() )
root = Tk()
root.title("variable測試")
App(root)
root.mainloop()#PhotoImage
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):# 創(chuàng)建一個(gè)位圖bm =PhotoImage(file='images/serial.png')#此處會報(bào)錯(cuò),先改成None跑一次,再轉(zhuǎn)成圖像self.label = ttk.Label(self.master, text='瘋狂體\n系圖書',image=bm , font=('StSong', 20, 'bold'), foreground='red' )self.label.bm = bmself.label['compound'] = Noneself.label.pack()f=ttk.Frame(self.master)# 創(chuàng)建Frame容器,用于裝多個(gè)Radiobuttonf.pack(fill=BOTH, expand=YES)self.var = StringVar()# 定義一個(gè)StringVar變量,用作綁定Radiobutton的變量self.var.set('None')compounds = ('None', "LEFT", "RIGHT", "TOP", "BOTTOM", "CENTER")for val in compounds:# 使用循環(huán)創(chuàng)建多個(gè)Radionbutton組件,variable=self.var就是說每個(gè)單選按鈕都綁定這個(gè)變量,變量值就是按鈕valueRadiobutton(f,text=val,padx=20,variable=self.var,command=self.change_compound,value=val).pack(side=LEFT,anchor=CENTER)def change_compound(self):self.label['compound'] = self.var.get().lower()
root = Tk()
root.title("compound測試")
App(root)
root.mainloop()#entry/text/messagebox
from tkinter import *
from tkinter import ttk
from tkinter import messagebox
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):self.entry=ttk.Entry(self.master,width=44,font=('StSong',14),foreground='green')self.entry.pack(fill=BOTH,expand=YES)self.text=Text(self.master,width=44,height=4,font=('StSong',14),foreground='gray')self.text.pack(fill=BOTH,expand=YES)f=Frame(self.master)f.pack()ttk.Button(f, text='開始處插入', command=self.insert_start).pack(side=LEFT)ttk.Button(f, text='光標(biāo)處插入', command=self.insert_edit).pack(side=LEFT)ttk.Button(f, text='結(jié)尾處插入', command=self.insert_end).pack(side=LEFT)ttk.Button(f, text='刪除文本', command=self.del_text).pack(side=LEFT)ttk.Button(f, text='獲取文本', command=self.get_text).pack(side=LEFT)def insert_start(self):self.entry.insert(0, 'Kotlin')self.text.insert(0.0, 'Kotlin')#第1行第0個(gè)字符處插入def insert_edit(self):self.entry.insert(INSERT, 'Python')self.text.insert(INSERT, 'Python')def insert_end(self):self.entry.insert(END, 'Swift')self.text.insert(END, 'Swift')def del_text(self):self.text.delete(1.0,END)#刪全部self.entry.delete(0)#刪一個(gè)字符def get_text(self):messagebox.showinfo(title='輸入內(nèi)容', message=self.entry.get())messagebox.showinfo(title='輸入內(nèi)容', message=self.text.get(1.0, END))
root = Tk()
root.title("Entry測試")
App(root)
root.mainloop()#webbrowser
import webbrowser
webbrowser.open('https://item.jd.com/12261787.html')#intVar/Radiobutton單選按鈕
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):ttk.Label(self.master, text='選擇您喜歡的單詞:').pack(fill=BOTH, expand=YES)self.intVar = IntVar()self.intVar.set(2)books = ('CJ', 'loves','GJL', 'forever')i = 1for book in books:ttk.Radiobutton(self.master,text=book,variable=self.intVar,command=self.change,value=i).pack(anchor=W)i += 1def change(self):print(self.intVar.get())
root = Tk()
root.title("Radiobutton測試")
App(root)
root.mainloop()#intVar/Checkbutton多選按鈕
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):self.chars = []for ch in ('孫悟空', '豬八戒','唐僧', '牛魔王'):intVar=IntVar()self.chars.append(intVar)ttk.Checkbutton(self.master,text=ch,variable=intVar,command=self.change).pack(anchor=W)#不加w會居中def change(self):print(','.join([str(e.get()) for e in self.chars]))
root = Tk()
root.title("Checkbutton測試")
root.iconbitmap('images/fklogo.ico')
App(root)
root.mainloop()#Listbox
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):#第一個(gè)frametopF = Frame(self.master)topF.pack(fill=Y, expand=YES)#列表框self.lb = Listbox(topF)self.lb.pack(side=LEFT, fill=Y, expand=YES)for item in ['Python', 'Kotlin', 'Swift', 'Ruby']:self.lb.insert(END, item)#self.lb.insert(ANCHOR, 'Python', 'Kotlin', 'Swift', 'Ruby')#與上一行等價(jià)self.lb.bind("<Double-1>", self.click)#列表框中的雙擊事件#滾動條scroll=Scrollbar(topF, command=self.lb.yview)# 創(chuàng)建Scrollbar組件,設(shè)置該組件與self.lb的縱向滾動關(guān)聯(lián)scroll.pack(side=RIGHT, fill=Y)self.lb.configure(yscrollcommand=scroll.set)# 設(shè)置self.lb的縱向滾動影響scroll滾動條#第二個(gè)framef = Frame(self.master)f.pack()#標(biāo)簽Label(f, text = '選擇模式:').pack(side=LEFT)#多選按鈕self.strVar = StringVar()self.strVar.set('browse')for m in ('multiple', 'browse', 'single', 'extended'):#單選可拖動,多選,單選必單擊,多選必ctrl/shiftttk.Radiobutton(f,text=m,value=m,variable=self.strVar,command=self.choose_mode).pack(side=LEFT)def choose_mode(self):print(self.strVar.get())self.lb['selectmode'] = self.strVar.get()def click(self, event):print(str(self.lb.curselection()))
root = Tk()
root.title("Listbox測試")
root.iconbitmap('images/fklogo.ico')
App(root)
root.mainloop()#Combobox
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):#下拉列表綁定字符串變量self.strVar = StringVar()self.cb = ttk.Combobox(self.master,textvariable=self.strVar,postcommand=self.choose)self.cb.pack(side=TOP)self.cb['values'] = ['Python', 'Ruby', 'Kotlin', 'Swift']#framef = Frame(self.master)f.pack()#多選按鈕綁定整型變量self.isreadonly = IntVar()Checkbutton(f, text = '是否只讀:',variable=self.isreadonly,command=self.change).pack(side=LEFT)Button(f, text = '綁定變量設(shè)置',command=self.setvalue).pack(side=LEFT)def choose(self):print(str(self.cb.get()))def change(self):self.cb['state'] = 'readonly' if self.isreadonly.get() else 'enable'#改cb的state屬性def setvalue(self):self.strVar.set('我愛Python')#改字符串變量
root = Tk()
root.title("Combobox測試")
root.iconbitmap('images/fklogo.ico')
App(root)
root.mainloop()#scale
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):self.doubleVar = DoubleVar()self.scale = Scale(self.master,from_ = -100, # 設(shè)置最大值to = 100, # 設(shè)置最小值resolution = 5, # 設(shè)置步長label = '示范Sacle', # 設(shè)置標(biāo)簽內(nèi)容length = 400, # 設(shè)置軌道的長度width = 30, # 設(shè)置軌道的寬度troughcolor='lightblue', # 設(shè)置軌道的背景色sliderlength=20, # 設(shè)置滑塊的長度sliderrelief=SUNKEN, # 設(shè)置滑塊的立體樣式showvalue=YES, # 設(shè)置顯示當(dāng)前值…………………………………這個(gè)就是本例中要控制的變量orient = HORIZONTAL, #設(shè)置水平方向………………………這個(gè)就是本例中要控制的變量digits = 10, # 設(shè)置十位有效數(shù)字command = self.change, # 綁定事件處理函數(shù)(value會自動傳過去)variable = self.doubleVar # 綁定變量(如果只是獲取的話不用綁定變量也可,直接self.scale.get()))self.scale.set(20)self.scale.pack()#第一個(gè)framef = Frame(self.master)f.pack(fill=X, expand=YES, padx=10)Label(f, text='是否顯示值:').pack(side=LEFT)self.showVar=IntVar()self.showVar.set(1)Radiobutton(f, text='不顯示', value=0,variable=self.showVar,command=self.switch_show).pack(side=LEFT)Radiobutton(f, text='顯示', value=1,variable=self.showVar,command=self.switch_show).pack(side=LEFT)#第一個(gè)framef = Frame(self.master)f.pack(fill=X, expand=YES, padx=10)Label(f, text='方向:').pack(side=LEFT)self.orientVar = IntVar()self.orientVar.set(0)Radiobutton(f, text='水平', value=0,variable=self.orientVar,command=self.switch_orient).pack(side=LEFT)Radiobutton(f, text='垂直', value=1,variable=self.orientVar,command=self.switch_orient).pack(side=LEFT)def switch_show(self):self.scale['showvalue'] = self.showVar.get()def switch_orient(self):self.scale['orient'] = VERTICAL if self.orientVar.get() else HORIZONTALdef change(self, value):print(value, self.scale.get(), self.doubleVar.get())
root = Tk()
root.title("Scale測試")
App(root)
root.mainloop()#LabeledScale(簡化版scale)
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):self.scale=ttk.LabeledScale(self.master,from_=-100,to=100,compound=BOTTOM)#設(shè)置顯示數(shù)值在下方self.scale.value = -20self.scale.pack(fill=X, expand=YES)
root = Tk()
root.title("LabeledScale測試")
App(root)
root.mainloop()#Labelframe(frame上有標(biāo)簽)
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):lf = ttk.Labelframe(self.master, text='請選擇',padding=20)lf.pack(fill=BOTH, expand=YES, padx=10, pady=10)i = 0self.intVar = IntVar()for book in ['CJ', 'LOVES', 'GJL', '1314']:Radiobutton(lf, text=book,value=i,variable=self.intVar,command=self.rb).pack(side=LEFT)i += 1 def rb(self):print(self.intVar.get())self.intVar.set((self.intVar.get()+1)%4)
root = Tk()
root.title("Labelframe測試")
# 改變窗口圖標(biāo)
root.iconbitmap('images/fklogo.ico')
App(root)
root.mainloop()#Panedwindow(用戶可拉動分界線)
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):#創(chuàng)建Panedwindow組件,通過style屬性配置分隔線style = ttk.Style()style.configure("fkit.TPanedwindow", background='darkgray', relief=RAISED)pwindow = ttk.Panedwindow(self.master,orient=VERTICAL, style="fkit.TPanedwindow") pwindow.pack(fill=BOTH, expand=1)#插入一般部件,add,remove,insertpwindow.add(ttk.Label(pwindow, text="this is a label"))okBn=ttk.Button(pwindow,text="this is a button",command=lambda:pwindow.remove(okBn))pwindow.add(okBn)# 因?yàn)樯厦鎟emove要引用okBn所以不能直接把創(chuàng)建代碼扔進(jìn)add里pwindow.add(ttk.Entry(pwindow, width=30))pwindow.insert(1, Label(pwindow, text="this is a label too"))#插入pwindow部件,創(chuàng)建pwindow子對象是水平方向rightwindow = PanedWindow(pwindow, orient=HORIZONTAL)pwindow.add(rightwindow)rightwindow.add(Label(rightwindow, text="左標(biāo)簽", background='lightgreen')) rightwindow.add(Label(rightwindow, text="右標(biāo)簽", background='lightblue'))
root = Tk()
root.title("Panedwindow測試")
App(root)
root.mainloop()#OptionMenu
from tkinter import *
from tkinter import ttk
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):#先建個(gè)可選菜單self.sv = StringVar()self.om = ttk.OptionMenu(root,self.sv,'CJ','CJ','loves','GJL',command=self.print_option)self.om.pack()#然后建個(gè)有標(biāo)簽的framelf = ttk.Labelframe(self.master, padding=20, text='choose:')lf.pack(fill=BOTH, expand=YES, padx=10, pady=10)#層里建單選按鈕self.directions = ['below', 'above', 'left', 'right', 'flush']i = 0self.intVar = IntVar()for direct in self.directions:Radiobutton(lf,text=direct,value=i,command=self.change,variable=self.intVar).pack(side=LEFT)i += 1def print_option(self, val):print(self.sv.get(), val)#其實(shí)就是綁定變量然后在函數(shù)里get就行了,同理set回去也可以def change(self):self.om['direction'] = self.directions[self.intVar.get()]#修改屬性
root = Tk()
root.title("OptionMenu測試")
root.iconbitmap('images/fklogo.ico')
App(root)
root.mainloop()#simpledialog,dialog提示對話框
from tkinter import *
from tkinter import ttk
from tkinter import simpledialog
from tkinter import dialog
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):ttk.Button(self.master,text='SimpleDialog',command=self.open_simpledialog).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master,text='Dialog',command=self.open_dialog).pack(side=LEFT, ipadx=5, ipady=5, padx = 10)def open_simpledialog(self):d = simpledialog.SimpleDialog(self.master, # 設(shè)置該對話框所屬的窗口title='SimpleDialog測試', # 標(biāo)題text='CJ loves GJL.', # 內(nèi)容cancel=3, # 用戶點(diǎn)擊x關(guān)閉對話框時(shí)返回值default=0, # 設(shè)置默認(rèn)是哪個(gè)按鈕得到焦點(diǎn)buttons=["是", "否", "取消"] )print(d.go()) #①def open_dialog(self):d = dialog.Dialog(self.master # 設(shè)置該對話框所屬的窗口, {'title': 'Dialog測試', # 標(biāo)題'text':'CJ loves GJL.', # 內(nèi)容'bitmap': 'question', # 圖標(biāo)'default': 0, # 設(shè)置默認(rèn)選中項(xiàng)'strings': ('確定','取消','退出')})print(d.num) #②
root = Tk()
root.title("對話框測試")
App(root)
root.mainloop()##askinteger輸入框
from tkinter import *
from tkinter import ttk
from tkinter import simpledialog
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):ttk.Button(self.master,text='int',command=self.open_integer).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master,text='float',command=self.open_float).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='str',command=self.open_string).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master,text='colour',command=self.choose_color).pack(side=LEFT,ipadx=5,ipady=5,padx= 10)def open_integer(self):print(simpledialog.askinteger("猜歲數(shù)","我老婆多少歲:",initialvalue=30,minvalue=10,maxvalue=50))def open_float(self):print(simpledialog.askfloat("猜體重","我老婆多少千克:",initialvalue=30,minvalue=10,maxvalue=50))def open_string(self):print(simpledialog.askstring("猜名字","我老婆叫什么名字:",initialvalue='GJL'))def choose_color(self):print(colorchooser.askcolor(parent=self.master, title='選擇畫筆顏色'))
root = Tk()
root.title("輸入對話框測試")
App(root)
root.mainloop()#message(共四部分:標(biāo)題,文字,圖標(biāo),按鈕)
from tkinter import *
from tkinter import ttk
from tkinter import messagebox as msgbox
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):#先弄個(gè)大frametopF = Frame(self.master)topF.pack(fill=BOTH)#大frame下設(shè)圖標(biāo)選擇lf1 = ttk.Labelframe(topF, text='請選擇圖標(biāo)類型')lf1.pack(side=LEFT, fill=BOTH, expand=YES, padx=10, pady=5)i = 0self.iconVar = IntVar()self.icons = [None, "error", "info", "question", "warning"]for icon in self.icons:Radiobutton(lf1, text = icon if icon is not None else '默認(rèn)',value=i,variable=self.iconVar).pack(side=TOP, anchor=W)i += 1self.iconVar.set(0)#大frame下設(shè)按鈕選擇lf2 = ttk.Labelframe(topF, text='請選擇按鈕類型')lf2.pack(side=LEFT,fill=BOTH, expand=YES, padx=10, pady=5)i = 0self.typeVar = IntVar()self.types = [None, "abortretryignore", "ok", "okcancel","retrycancel", "yesno", "yesnocancel"]for tp in self.types:Radiobutton(lf2, text= tp if tp is not None else '默認(rèn)',value=i,variable=self.typeVar).pack(side=TOP, anchor=W)i += 1self.typeVar.set(0)#最下面是按鈕事件bottomF = Frame(self.master)bottomF.pack(fill=BOTH)btn1 = ttk.Button(bottomF, text="showinfo",command=self.showinfo_clicked)btn1.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn2 = ttk.Button(bottomF, text="showwarning",command=self.showwarning_clicked)btn2.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn3 = ttk.Button(bottomF, text="showerror",command=self.showerror_clicked)btn3.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn4 = ttk.Button(bottomF, text="askquestion",command=self.askquestion_clicked)btn4.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn5 = ttk.Button(bottomF, text="askokcancel",command=self.askokcancel_clicked)btn5.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn6 = ttk.Button(bottomF, text="askyesno",command=self.askyesno_clicked)btn6.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn7 = ttk.Button(bottomF, text="askyesnocancel",command=self.askyesnocancel_clicked)btn7.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)btn8 = ttk.Button(bottomF, text="askretrycancel",command=self.askretrycancel_clicked)btn8.pack(side=LEFT, fill=X, ipadx=5, ipady=5,pady=5, padx=5)def showinfo_clicked(self):print(msgbox.showinfo("Info", "showinfo測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def showwarning_clicked(self):print(msgbox.showwarning("Warning", "showwarning測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def showerror_clicked(self):print(msgbox.showerror("Error", "showerror測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def askquestion_clicked(self):print(msgbox.askquestion("Question", "askquestion測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def askokcancel_clicked(self):print(msgbox.askokcancel("OkCancel", "askokcancel測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def askyesno_clicked(self):print(msgbox.askyesno("YesNo", "askyesno測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def askyesnocancel_clicked(self):print(msgbox.askyesnocancel("YesNoCancel", "askyesnocancel測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))def askretrycancel_clicked(self):print(msgbox.askretrycancel("RetryCancel", "askretrycancel測試.",icon=self.icons[self.iconVar.get()],type=self.types[self.typeVar.get()]))
root = Tk()
root.title("消息框測試")
App(root)
root.mainloop()#filedialog(注意返回值是文件還是文件名/路徑)
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):ttk.Button(self.master, text='打開單個(gè)文件',command=self.open_file).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='打開多個(gè)文件',command=self.open_files).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='獲取單個(gè)打開文件的文件名',command=self.open_filename).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='獲取多個(gè)打開文件的文件名',command=self.open_filenames).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='獲取保存文件',command=self.save_file).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='獲取保存文件的文件名',command=self.save_filename).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)ttk.Button(self.master, text='打開路徑',command=self.open_dir).pack(side=LEFT, ipadx=5, ipady=5, padx= 10)def open_file(self):# 調(diào)用askopenfile方法獲取單個(gè)打開的文件print(filedialog.askopenfile(title='打開單個(gè)文件',filetypes=[("文本文件", "*.txt"), ('Python源文件', '*.py')],initialdir='g:/'))def open_files(self):# 調(diào)用askopenfile方法獲取多個(gè)打開的文件print(filedialog.askopenfiles(title='打開多個(gè)文件',filetypes=[("文本文件", "*.txt"), ('Python源文件', '*.py')],initialdir='g:/')) def open_filename(self):# 調(diào)用askopenfilename方法獲取單個(gè)文件的文件名print(filedialog.askopenfilename(title='打開單個(gè)文件',filetypes=[("文本文件", "*.txt"), ('Python源文件', '*.py')],initialdir='g:/')) def open_filenames(self):# 調(diào)用askopenfilenames方法獲取多個(gè)文件的文件名print(filedialog.askopenfilenames(title='打開多個(gè)文件',filetypes=[("文本文件", "*.txt"), ('Python源文件', '*.py')],initialdir='g:/')) def save_file(self):# 調(diào)用asksaveasfile方法保存文件print(filedialog.asksaveasfile(title='保存文件',filetypes=[("文本文件", "*.txt"), ('Python源文件', '*.py')],initialdir='g:/'))def save_filename(self):# 調(diào)用asksaveasfilename方法獲取保存文件的文件名print(filedialog.asksaveasfilename(title='保存文件',filetypes=[("文本文件", "*.txt"), ('Python源文件', '*.py')],initialdir='g:/'))def open_dir(self):# 標(biāo)題,初始路徑,比上面的方法少了個(gè)文件類型(因?yàn)楝F(xiàn)在打開的是路徑)print(filedialog.askdirectory(title='打開目錄',initialdir='g:/')) # 初始目錄
root = Tk()
root.title("文件對話框測試")
App(root)
root.mainloop()#Menu(command/checkbutton/radiobutton/separator,label標(biāo)簽/command方法/image貼圖/compound方位)
from tkinter import *
from tkinter import ttk
from tkinter import messagebox as msgbox
class App:def __init__(self, master):self.master = masterself.init_menu()def init_menu(self):#一、總菜單對象menubar = Menu(self.master)self.master['menu'] = menubar#二、主菜單對象file_menu = Menu(menubar, tearoff=0)# 創(chuàng)建file_menu菜單,它被放入menubar中l(wèi)ang_menu = Menu(menubar, tearoff=0)# 創(chuàng)建lang_menu菜單,它被放入menubar中menubar.add_cascade(label='文件', menu=file_menu)# 使用add_cascade方法添加file_menu菜單menubar.add_cascade(label='語言', menu=lang_menu)# 使用add_cascade方法添加lang_menu菜單#三、為file_menu添加下拉菜單(注意加add_command是葉子項(xiàng),加add_cascade是子級菜單)self.master.filenew_icon = PhotoImage(file='images/filenew.png')self.master.fileopen_icon = PhotoImage(file='images/fileopen.png')file_menu.add_command(label="新建", command = None,image=self.master.filenew_icon, compound=LEFT)file_menu.add_command(label="打開", command = None,image=self.master.fileopen_icon, compound=LEFT)file_menu.add_separator()#分隔條sub_menu = Menu(file_menu, tearoff=0)# 創(chuàng)建sub_menu菜單,它被放入file_menu中file_menu.add_cascade(label='性別', menu=sub_menu) #使用add_cascade方法添加sub_menu子菜單#四、為sub_menu添加子菜單(注意加了add_radiobutton單選按鈕)self.genderVar = IntVar()for i, im in enumerate(['男', '女', '保密']):# 使用enumerate循環(huán)為sub_menu子菜單添加菜單項(xiàng)(特別注意這里的寫法)sub_menu.add_radiobutton(label=im,command=self.choose_gender,variable=self.genderVar, value=i)#枚舉標(biāo)簽,同方法,同變量,枚舉值#五、為lang_menu添加下拉菜單(注意加了add_checkbutton多選按鈕)self.langVars = [StringVar(), StringVar(), StringVar(), StringVar()]for i, im in enumerate(('Python', 'Kotlin','Swift', 'Java')):lang_menu.add_checkbutton(label=im, command=self.choose_lang,onvalue=im, variable=self.langVars[i])def choose_gender(self):msgbox.showinfo(message=('選擇的性別為: %s' % self.genderVar.get()))def choose_lang(self):rt_list = [e.get() for e in self.langVars]msgbox.showinfo(message=('選擇的語言為: %s' % ','.join(rt_list)))
root = Tk()
root.title("菜單測試")
root.geometry('400x200')
root.resizable(width=False, height=False)#禁止改變窗口大小
App(root)
root.mainloop()#右鍵菜單(函數(shù)傳參寫法)
from tkinter import *
from tkinter import ttk
from collections import OrderedDict
class App:def __init__(self, master):self.master = masterself.initWidgets()def initWidgets(self):#主界面就是一個(gè)textself.text=Text(self.master,height=12,width=60,foreground='darkgray',font=('微軟雅黑',12),spacing2=8,spacing3=12)self.text.insert(END,'CJ loves GJL.')self.text.pack()self.text.bind('<Button-3>',self.popup)self.text.bind('<Up>', self.keyup)#右鍵一級菜單是m1與m2self.popup_menu = Menu(self.master,tearoff = 0)m1 = Menu(self.popup_menu, tearoff = 0)m2 = Menu(self.popup_menu, tearoff = 0)self.popup_menu.add_cascade(label='fc',menu = m1)self.popup_menu.add_cascade(label='bc',menu = m2)#m1下的菜單是rgb三個(gè),通過用variable綁定value來換前景色self.fcVar=StringVar()m1.add_radiobutton(label='r',command=self.choose1,variable=self.fcVar,value='red')m1.add_radiobutton(label='b',command=self.choose1,variable=self.fcVar,value='blue')m1.add_radiobutton(label='g',command=self.choose1,variable=self.fcVar,value='green')#m2下的菜單也是rgb三個(gè),但是用換了一種函數(shù)寫法來換背景色self.my_items=OrderedDict([('紅色','red'), ('綠色','green'), ('藍(lán)色', 'blue')])for i in self.my_items:m2.add_command(label=i,command=self.handlerAdaptor(self.choose2,val=i))def popup(self, event):self.popup_menu.post(event.x_root,event.y_root)def choose1(self):self.text['foreground'] = self.fcVar.get()def choose2(self,val):self.text['background'] = self.my_items[val]def handlerAdaptor(self, fun,**kwds):return lambda fun=fun, kwds=kwds: fun(**kwds)def keyup(self, event):print('up',event)#up <KeyPress event state=Mod1|0x40000 keysym=Up keycode=38 x=149 y=261>
root = Tk()
root.title("右鍵菜單測試")
App(root)
root.mainloop()#tearoff=1時(shí)的情況:能獨(dú)立出來
import tkinter
root = tkinter.Tk()
root.title('menu')
menu = tkinter.Menu(root)
submenu = tkinter.Menu(menu, tearoff = 1)
submenu.add_command(label = '打開')
menu.add_cascade(label = '文件', menu = submenu)
root.config(menu = menu)
root.mainloop()#Canvas
from tkinter import *
root = Tk()
cv = Canvas(root, background='white')
cv.pack(fill=BOTH, expand=YES)
cv.create_rectangle(30, 30, 200, 200,outline='red',stipple = 'question',fill="blue",width=5)
cv.create_oval(240, 30, 330, 200,outline='yellow',fill='pink',width=4)
Canvas.create_window(cv, 0, 0, window=Button(cv,text = '單擊我', padx=10, pady=5,command = lambda :print('按鈕單擊')),anchor=NW)
root.mainloop()#tag_bind與focus_set/bind
from tkinter import *
def first(event):print('第一次的函數(shù)')
def second(event):print('第二次的函數(shù)')
def move_left(event):print('left')
root = Tk()
cv = Canvas(root,bg = 'white')# 創(chuàng)建一個(gè)Canvas,設(shè)置其背景色為白色
cv.pack()
cv.create_rectangle(30, 30, 220, 150,width = 8,tags = ('r1','r2','r3'))
cv.tag_bind('r1','<Button-1>', first)# 為指定圖形項(xiàng)的左鍵單擊事件綁定處理函數(shù)
cv.tag_bind('r1','<Button-1>', second, add=True)# add為True是添加,否則是替代
cv.focus_set()#讓畫布得到焦點(diǎn),才可以響應(yīng)按鍵事件
cv.bind('<Left>',move_left)
root.mainloop()
#第十二章:文件IO
#PurePath自動轉(zhuǎn)PureWindowsPath
from pathlib import *
print(type(PurePath('setup.py'))) # <class 'pathlib.PureWindowsPath'>,自動轉(zhuǎn)為win格式
print(PurePath('crazyit', 'some/path', 'info')) # 'crazyit\some\path\info'
print(PurePath(Path('crazyit'), Path('info'))) # 'crazyit\info'
print(PurePosixPath('crazyit','some/path' 'info')) # crazyit/some/path/info,Unix風(fēng)格的路徑
print(PurePath()) # . 不傳入?yún)?shù),默認(rèn)使用當(dāng)前路徑
print(PurePosixPath('/etc', '/usr','lib64'))# /usr/lib64,傳入?yún)?shù)包含多個(gè)根路徑
print(PureWindowsPath('c:/Windows','d:info'))# d:info,僅最后一個(gè)根路徑及后面子路徑生效
print(PureWindowsPath('c:/Windows','/Program Files'))#c:\Program Files,在Win中盤符才算根路徑
print(PurePath('crazyit//info')) # crazyit\info,路徑字符串中多出來的斜杠和點(diǎn)號都會被忽略
print(PurePath('crazyit/./info')) # crazyit\info
print(PurePath('crazyit/../info')) # crazyit\..\info,相當(dāng)于找和crazyit同一級的info路徑
print(PurePosixPath('info') == PurePosixPath('INFO'))# False比較Unix風(fēng)格路徑區(qū)分大小寫
print(PureWindowsPath('info') == PureWindowsPath('INFO')) # True比較WIN風(fēng)格路徑不區(qū)分大小寫
print(PureWindowsPath('crazyit') == PurePosixPath('crazyit')) # False不同風(fēng)格路徑總不等
print(PureWindowsPath('abc') / 'xyz' / 'wawa') # abc\xyz\wawa(Win風(fēng)格的路徑)
print(PurePosixPath('abc') / 'xyz' / 'wawa') # abc/xyz/wawa(Unix風(fēng)格的路徑)
print(str(PureWindowsPath('abc','xyz','wawa'))) # abc\xyz\wawa
print(str(PurePosixPath('abc', 'xyz', 'wawa'))) # abc/xyz/wawa#PurePath的屬性
from pathlib import *
# 訪問drive屬性:驅(qū)動器盤符
print(PureWindowsPath('c:/Program Files/').drive) # c:
print(PureWindowsPath('/Program Files/').drive) # ''
print(PurePosixPath('/etc').drive) # ''
# 訪問root屬性:根路徑
print(PureWindowsPath('c:/Program Files/').root) # \
print(PureWindowsPath('c:Program Files/').root) # ''
print(PurePosixPath('/etc').root) # /
# 訪問anchor屬性:盤符與根路徑
print(PureWindowsPath('c:/Program Files/').anchor) # c:\
print(PureWindowsPath('c:Program Files/').anchor) # c:
print(PurePosixPath('/etc').anchor) # /
# 訪問parents屬性:全部父路徑
pp = PurePath('abc/xyz/wawa/haha')
print(pp.parents[0]) # abc\xyz\wawa
print(pp.parents[1]) # abc\xyz
print(pp.parents[2]) # abc
print(pp.parents[3]) # .
# 訪問parent屬性:上一級路徑,相當(dāng)于parents[0]
print(pp.parent) # abc\xyz\wawa
# 訪問name屬性:當(dāng)前路徑文件名
print(PurePath('abc/wawa/bb.txt').name) # bb.txt
# 訪問suffixes屬性:所有后綴名
pp = PurePath('abc/wawa/bb.txt.tar.zip')
print(pp.suffixes[0]) # .txt
print(pp.suffixes[1]) # .tar
print(pp.suffixes[2]) # .zip
# 訪問suffix屬性:suffixes最后一個(gè)值
print(pp.suffix) # .zip
# 訪問stem屬性:當(dāng)前路徑主文件名
print(pp.stem) # bb.txt.tar
# 類型轉(zhuǎn)換方法
pp = PurePath('d:/', 'Python', 'Python3.6')
print(pp.as_posix()) # d:/Python/Python3.6,轉(zhuǎn)成Unix風(fēng)格的路徑
print(pp.as_uri()) # file:///d:/Python/Python3.6,絕對路徑轉(zhuǎn)換成Uri
# 判斷當(dāng)前路徑是否匹配指定模式
print(PurePath('a/b.py').match('*.py')) # True
print(PurePath('/a/b/c.py').match('b/*.py')) # True
print(PurePath('/a/b/c.py').match('a/*.py')) # False
# 測試relative_to方法:去除基準(zhǔn)路徑的路徑
pp = PurePosixPath('c:/abc/xyz/wawa')
print(pp.relative_to('c:/')) # abc\xyz\wawa
print(pp.relative_to('c:/abc')) # xyz\wawa
print(pp.relative_to('c:/abc/xyz')) # wawa
# 測試with_name方法:把當(dāng)前路徑文件名替換掉(當(dāng)前路徑無文件名會報(bào)錯(cuò))
p = PureWindowsPath('e:/Downloads/pathlib.tar.gz')
print(p.with_name('fkit.py')) # e:\Downloads\fkit.py
# 測試with_suffix方法:把當(dāng)前路徑文件名后綴替換掉,若沒有后綴則加上
print(PureWindowsPath('e:/pathlib.tar.gz').with_suffix('.zip')) # e:\pathlib.tar.zip
print(PureWindowsPath('README').with_suffix('.txt')) # README.txt#Path的屬性
from pathlib import *
for x in Path('.').iterdir():print(x)#當(dāng)前目錄下所有文件與子目錄
for x in Path('../').glob('**/*.py'):print(x)#上級目錄及其所有子目錄下的的py文件
p = Path('a_test.txt')
print(p.write_text('''I LOVE GJL''', encoding='GBK'))# 返回輸出的字符數(shù)
print(p.read_text(encoding='GBK'))# 輸出讀取的文本內(nèi)容
print(p.read_bytes())# 讀取字節(jié)內(nèi)容#os.path的屬性
import os
import time
print(os.path.abspath("abc.txt")) # G:\publish\codes\12\12.2\abc.txt 獲取絕對路徑
print(os.path.commonprefix(['/usr/lib', '/usr/local/lib'])) # /usr/l 獲取共同前綴
print(os.path.commonpath(['/usr/lib', '/usr/local/lib'])) # \usr 獲取共同路徑
print(os.path.dirname('abc/xyz/README.txt')) #abc/xyz 獲取目錄
print(os.path.exists('abc/xyz/README.txt')) # False 判斷指定目錄是否存在
print(time.ctime(os.path.getatime('a_test.txt')))# 獲取最近一次訪問時(shí)間
print(time.ctime(os.path.getmtime('a_test.txt')))# 獲取最后一次修改時(shí)間
print(time.ctime(os.path.getctime('a_test.txt')))# 獲取創(chuàng)建時(shí)間
print(os.path.getsize('a_test.txt'))# 獲取文件大小
print(os.path.isfile('a_test.txt')) # True 判斷是否為文件
print(os.path.isdir('a_test.txt')) # False 判斷是否為目錄
print(os.path.samefile('a_test.txt', './a_test.txt')) # True 判斷是否為同一個(gè)文件#fnmatch:file name match
from pathlib import *
import fnmatch
#fnmatch:對文件名進(jìn)行匹配
for file in Path('.').iterdir():#遍歷當(dāng)前目錄下所有文件和子目錄if fnmatch.fnmatch(file,'*.PY'):print(file)# 訪問所有以_test.py結(jié)尾的文件
#filter:對列表中的串進(jìn)行匹配
names = ['a.py', 'b.py', 'c.py', 'd.py']
print(fnmatch.filter(names, '[ac].py')) # ['a.py', 'c.py']
#translate:把UNIX的shell風(fēng)格轉(zhuǎn)換成pattern風(fēng)格
print(fnmatch.translate('?.py')) # (?s:.\.py)\Z
print(fnmatch.translate('[ac].py')) # (?s:[ac]\.py)\Z
print(fnmatch.translate('[a-c].py')) # (?s:[a-c]\.py)\Z#寫文件
#一、默認(rèn)生成的txt文件使用的編碼是ANSI
import os
f = open('ANSI_test.txt', 'w+')#清空寫入
f.write('我愛龔嘉露13' + os.linesep)# os.linesep代表當(dāng)前操作系統(tǒng)上的換行符
f.writelines(('CJ'+os.linesep,'LOVES'+os.linesep,'GJL'+os.linesep))
f.close()
f = open('ANSI_test.txt', 'a+')#追加寫入
f.write('我愛龔嘉露14' + os.linesep)# os.linesep代表當(dāng)前操作系統(tǒng)上的換行符
f.writelines(('CJ'+os.linesep,'LOVES'+os.linesep,'GJL'+os.linesep,'1314'+ os.linesep))
f.close()
#二、生成以utf-8編碼的txt文件要用二進(jìn)制打開再顯式設(shè)置utf-8
f = open('utf-8_test.txt', 'wb+')
f.write(('陳俊愛龔嘉露' + os.linesep).encode('utf-8'))
f.writelines((('I'+os.linesep).encode('utf-8'),('love'+os.linesep).encode('utf-8'),('GJL'+os.linesep).encode('utf-8')))
f.close()
#三、ANSI編碼方式的讀入
f=open("ANSI_test.txt", 'r+', True)
print(f.read())
f.close()
#四、utf-8編方式的讀入
#(1)使用codecs讀入時(shí)直接以編碼形式讀
import codecs
f=codecs.open('utf-8_test.txt', 'r+', 'utf-8', buffering=True)
print(f.read())
f.close()
#(2)先以二進(jìn)制形式讀入再轉(zhuǎn)換編碼
f=open('utf-8_test.txt','rb+',True) #指定使用二進(jìn)制方式讀取文件內(nèi)容,得到的是bytes類型
print(f.read().decode('utf-8')) #用bytes的decode可將字節(jié)內(nèi)容恢復(fù)成字符串
f.close()
#(3)補(bǔ)充:若上面輸出不decode的話會得到
f=open('utf-8_test.txt','rb+',True) #指定使用二進(jìn)制方式讀取文件內(nèi)容,得到的是bytes類型
print(f.read())#b'\xe9\x99\x88\xe4\xbf\x8a\xe7\x88\xb1\xe9\xbe\x9a\xe5\x98\x89\xe9\x9c\xb2\r\nI\r\nlove\r\nGJL\r\n'
f.close()
'''字符串前綴
一、字符串前加 r
r" " 的作用是去除轉(zhuǎn)義字符
str1= 'input\n'
str= r'input\n'
print(str1)#input
print(str)#input\n
二、字符串前加 b
b" "前綴表示后面字符串是bytes類型
網(wǎng)絡(luò)編程中,服務(wù)器和瀏覽器只認(rèn)bytes類型數(shù)據(jù)
在 Python3 中,bytes 和 str 的互相轉(zhuǎn)換方式是
str.encode('utf-8')
bytes.decode('utf-8')
三、字符串前加 u
例:u"我是含有中文字符組成的字符串。"
后面字符串以 Unicode 格式編碼,防止因源碼儲存格式問題,導(dǎo)致再次使用時(shí)亂碼
'''#讀文件
#零、熱身
f = open('a_test.txt') # 默認(rèn)打開方式
print(f.encoding) # cp936 訪問文件的編碼方式此處即utf-8
print(f.mode) # r 訪問文件的訪問模式
print(f.closed) # False 訪問文件是否已經(jīng)關(guān)閉
print(f.name) # a_test.txt 訪問文件對象打開的文件名
'''(用三個(gè)+即可,二進(jìn)制讀入再加b)
r:只讀(不清空,指針在開頭)
w:只寫(先清空)
a:只寫(不清空,指針在結(jié)尾)
r+:讀寫(不清空,指針在開頭)
w+:讀寫(先清空)
a+:讀寫(不清空,指針在結(jié)尾)
b:以二進(jìn)制形式讀寫文件,用于非文本文件
'''
#一、逐字符讀(第三個(gè)參數(shù)True表示使用緩沖)
f = open("a_test.txt", 'r', True)
while True:ch = f.read(1) # 每次讀取一個(gè)字符if not ch: break # 如果沒有讀到數(shù)據(jù),跳出循環(huán)print(ch, end='') # 輸出ch
f.close()
#二、一次讀完
f = open("a_test.txt", 'r', True)
print(f.read())# 直接讀取全部文件
f.close()
#三、逐行讀出
import codecs
f = codecs.open("a_test.txt", 'r', 'utf-8', buffering=True)
while True:line = f.readline() # 每次讀取一行(其實(shí)就是遇\r\n或EOF為止),指針自動下移if not line: break # 如果沒有讀到數(shù)據(jù),跳出循環(huán)print(line, end='') # 輸出line
f.close()
import codecs
f = codecs.open("a_test.txt", 'r', 'utf-8', buffering=True)
for l in f.readlines():# 使用readlines()讀取所有行,返回所有行組成的列表print(l, end='')
f.close()
#四、讀多文件
import fileinput
for line in fileinput.input(files=('a_test.txt', 'a_test.txt')):print(fileinput.filename(), fileinput.filelineno(), line, end='')#名,行號,行
fileinput.close()# 關(guān)閉文件流
#五、with:該語句會負(fù)責(zé)關(guān)閉文件
import codecs
with codecs.open("a_test.txt", 'r', 'utf-8', buffering=True) as f:for line in f:print(line, end='')
import fileinput
with fileinput.input(files=('a_test.txt', 'a_test.txt')) as f:for line in f:print(line, end='')
#六、with關(guān)鍵字原理:__enter__與__exit__
class FkResource:def __init__(self, tag):self.tag = tagprint('類構(gòu)造器: %s' % tag)def __enter__(self):# 定義__enter__方法,with體之前的執(zhí)行的方法print('[__enter__ %s]: ' % self.tag)return '我是'+self.tag # 該返回值將作為as子句中變量的值def __exit__(self, exc_type, exc_value, exc_traceback):print('[__exit__ %s]: ' % self.tag)if exc_traceback is None:# exc_traceback為None,代表沒有異常print('無異常,關(guān)閉資源')else:print('有異常,關(guān)閉資源')return False # 可以省略,默認(rèn)返回None也被看做是False
with FkResource('孫悟空') as dr:print('[with代碼塊] 開始')print(dr)#正常執(zhí)行print('[with代碼塊] 結(jié)束')
print('------------------------------')
with FkResource('白骨精'):print('[with代碼塊] 開始')#raise Exception#出現(xiàn)異常print('[with代碼塊] 結(jié)束')
#七、讀指定行
import linecache
print(linecache.getline('a_test.txt', 2))# 讀取普通文件的第2行
#八、用seek操作指針位置,tell訪問指針下標(biāo),read讀取字節(jié)
f=open('Python_test2.py', 'rb')
print(f.tell()) # 0,當(dāng)前文件指針的位置
f.seek(3) # 將文件指針移動到3處
print(f.tell()) # 3,當(dāng)前文件指針的位置
print(f.read(1)) # b'p',讀取一個(gè)字節(jié),文件指針自動后移1個(gè)數(shù)據(jù)
print(f.tell()) # 4,當(dāng)前文件指針的位置
f.seek(5) # 將文件指針移動到5處,與f.seek(5,0)等價(jià),以開頭為基準(zhǔn)
print(f.tell()) # 5
f.seek(5, 1) # 將文件指針向后移動5個(gè)數(shù)據(jù),以指針當(dāng)前位置為基準(zhǔn)
print(f.tell()) # 10
f.seek(-10, 2) # 將文件指針移動到倒數(shù)第10處,以指針結(jié)尾位置為基準(zhǔn)
print(f.tell()) # 574
print(f.read(1)) # b')'
'''
問:在哪里查看一個(gè)txt文件格式的編碼?
答:打開文檔,點(diǎn)另存為,最下面編碼欄默認(rèn)顯示的即是當(dāng)前文件的編碼格式。
問:關(guān)于編碼方式之間的關(guān)系:
一、ANSI,最原始的ASCII碼,只有127位(但現(xiàn)在說的ANSI是含有GBK的ANSI)
二、ASCII+擴(kuò)展字符,變成255位
三、GB2312,中國人取消掉127位以后的符號,在原ASCII碼基礎(chǔ)上加入6000多個(gè)漢字
······此時(shí),原ACSII碼若用兩字節(jié)表示叫全角字符,用一字節(jié)表示叫半角字符(如,和,)
······區(qū)分全/半角:一個(gè)小于127的字符意義不變,但兩個(gè)大于127的字符連在一起就表示一個(gè)漢字
四、GBK,在GB2312基礎(chǔ)上加入20000個(gè)新的漢字(包括繁體字)和符號
······不要求低字節(jié)一定是127后的內(nèi)碼,只要第一個(gè)字節(jié)是大于127就固定表示這是一個(gè)漢字的開始
······現(xiàn)在所說的ANSI就是指原ASCII加上GBK擴(kuò)展包的,我的手提筆記本默認(rèn)是ANSI編碼格式
五、GB18030,在GBK基礎(chǔ)上加入幾千個(gè)新的少數(shù)民族的字
六、UNICODE,世界各國都搞編碼系統(tǒng)太亂,ISO出臺的統(tǒng)一編碼系統(tǒng),全球通用
······用兩字節(jié)表示一字符,總共可以組合出65535個(gè)字符,可覆蓋世界上所有文化的符號
······半角英文符號只需要用到低8位,所以其高8位永遠(yuǎn)是0,雖然浪費(fèi)但是硬盤空間已不是問題
······筆記本另存為中除了ANSI,Unicode,UTF-8外還有一項(xiàng)Unicode big endian是大端模式
七、UTF(UCS Transfer Format),用于傳輸,UTF8是每次8個(gè)位傳輸數(shù)據(jù),UTF16是每次16個(gè)位
'''#目錄
import os
print(os.getcwd()) # 獲取當(dāng)前目錄F:\ProjectPython\hello_test2
os.chdir('F:') # ch=change改變當(dāng)前目錄
os.mkdir('my_dir',0o755)#在當(dāng)前目錄創(chuàng)建目錄,755是所有者/組用戶/其他用戶的讀/寫/執(zhí)行權(quán)限
os.makedirs("abc/xyz/wawa", 0o755) # 遞歸創(chuàng)建目錄
os.rename('my_dir', 'your_dir') # 直接重命名當(dāng)前目錄下的子目錄
os.renames("abc/xyz/wawa", 'foo/bar/haha') # 遞歸重命名子目錄
os.rmdir('your_dir') # 直接刪除當(dāng)前目錄下的子目錄
os.removedirs('foo/bar/haha') # 遞歸刪除子目錄
#權(quán)限
print(os.access('.', os.F_OK|os.R_OK|os.W_OK|os.X_OK))#當(dāng)前目錄權(quán)限F存在R讀W寫X執(zhí)行
print(os.access('Python_test2.py', os.F_OK|os.R_OK|os.W_OK|os.X_OK))#文件權(quán)限
#鏈接
#os.symlink('Python_test4.py', 'soft_link.py')#創(chuàng)建快捷方式(WIN下要管理員權(quán)限)
#os.link('Python_test4.py', 'hard_link.py')#創(chuàng)建硬連接(Windows上就是復(fù)制文件)
#臨時(shí)
import tempfile
fp = tempfile.TemporaryFile()# 創(chuàng)建臨時(shí)文件
print(fp.name)
fp.write('兩情若是久長時(shí),'.encode('utf-8'))
fp.write('又豈在朝朝暮暮。'.encode('utf-8'))
fp.seek(0)# 將文件指針移到開始處,準(zhǔn)備讀取文件
print(fp.read().decode('utf-8')) # 輸出剛才寫入的內(nèi)容
fp.close()#此時(shí)關(guān)閉就會自動刪除
with tempfile.TemporaryFile() as fp:#通過with語句創(chuàng)建臨時(shí)文件,塊結(jié)束時(shí)自動關(guān)閉并刪除臨時(shí)文fp.write(b'I Love Python!')# 寫入內(nèi)容fp.seek(0)# 將文件指針移到開始處,準(zhǔn)備讀取文件print(fp.read()) # b'I Love Python!'# 讀取文件內(nèi)容
with tempfile.TemporaryDirectory() as tmpdirname:# 通過with語句創(chuàng)建臨時(shí)目錄print('創(chuàng)建臨時(shí)目錄', tmpdirname)
#第十三章:數(shù)據(jù)庫
#sqlite3
import sqlite3
conn = sqlite3.connect('first.db')# ①、打開或創(chuàng)建數(shù)據(jù)庫
c = conn.cursor()# ②、獲取游標(biāo)#增
c.execute('''create table user_tb(_id integer primary key autoincrement,name text,pass text,gender text)''')#執(zhí)行DDL語句創(chuàng)建數(shù)據(jù)表
#插
c.execute('insert into user_tb values(null, ?, ?, ?)',('孫悟空', '123456', 'male'))#調(diào)用執(zhí)行insert語句插入數(shù)據(jù)
#改
c.executemany('update user_tb set name=? where _id=?',(('小孫',2),('小白',3),('小豬',4)))#調(diào)用executemany()方法同時(shí)修改多個(gè)語句
print('修改的記錄條數(shù):',c.rowcount)# 通過rowcount獲取被修改的記錄條數(shù)
#查
c.execute('select * from user_tb where _id > ?', (2,))#調(diào)用執(zhí)行select語句查詢數(shù)據(jù)
print('查詢返回的記錄數(shù):', c.rowcount)
for col in (c.description):print(col[0], end='\t')#通過游標(biāo)的description屬性獲取列信息
print('\n--------------------------------')
while True:row = c.fetchone()# 獲取一行記錄,每行數(shù)據(jù)都是一個(gè)元組if not row :break# 如果抓取的row為None,退出循環(huán)print(row)
#SQL腳本
c.executescript('''insert into user_tb values(null, '武松', '3444', 'male')''')# 執(zhí)行一段SQL腳本
#自定義函數(shù)
def reverse_ext(st):# 先定義一個(gè)普通函數(shù),準(zhǔn)備注冊為SQL中的自定義函數(shù)return '[' + st[::-1] + ']'# 對字符串反轉(zhuǎn),前后加方括號
conn.create_function('enc', 1, reverse_ext)## 調(diào)用create_function注冊自定義函數(shù):enc,這句要放在c游標(biāo)賦值之前
c.execute('insert into user_tb values(null, ?, enc(?), ?)', ('賈寶玉', '123456', 'male'))# 在SQL語句中使用enc自定義函數(shù)
#聚集函數(shù)
class MinLen:# 先定義一個(gè)普通類,準(zhǔn)備注冊為SQL中的自定義聚集函數(shù)def __init__(self):self.min_len = Nonedef step(self, value):if self.min_len is None : # 如果self.min_len還未賦值,直接將當(dāng)前value賦值給self.min_linself.min_len = valuereturnif len(self.min_len) > len(value):# 找到一個(gè)長度更短的value,用value代替self.min_lenself.min_len = valuedef finalize(self):return self.min_len
conn.create_aggregate('min_len', 1, MinLen)# 調(diào)用聚集函數(shù)名字,所需參數(shù)數(shù)目,函數(shù)實(shí)現(xiàn)類,這句要放在c游標(biāo)賦值之前
c.execute('select min_len(pass) from user_tb')# 在SQL語句中使用min_len自定義聚集函數(shù)
print(c.fetchone()[0])#輸出user_tb表中長度最短的密碼
#比較函數(shù)
def my_collate(st1, st2):# 去掉字符串第一個(gè)、最后一個(gè)字符后比較大小if st1[1: -1] == st2[1: -1]:return 0elif st1[1: -1] > st2[1: -1]:return 1else:return -1
conn.create_collation('sub_cmp', my_collate)# 調(diào)用create_collation注冊自定義比較函數(shù):sub_cmp,這句要放在c游標(biāo)賦值之前
c.execute('select * from user_tb order by pass collate sub_cmp')# ③、在SQL語句中使用sub_cmp自定義的比較函數(shù)
for row in c:print(row)# 采用for循環(huán)遍歷游標(biāo),不需要fetchone()conn.commit()
c.close()# ④、關(guān)閉游標(biāo)
conn.close()# ⑤、關(guān)閉連接'''
DDL(data definition language): DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定義或改變表(TABLE)的結(jié)構(gòu),數(shù)據(jù)類型,表之間的鏈接和約束等初始化工作上,他們大多在建立表時(shí)使用,不需要commitDML(data manipulation language): 它們是SELECT、UPDATE、INSERT、DELETE,就象它的名字一樣,這4條命令是用來對數(shù)據(jù)庫里的數(shù)據(jù)進(jìn)行操作的語言,需要commitDCL(Data Control Language): 是數(shù)據(jù)庫控制功能。是用來設(shè)置或更改數(shù)據(jù)庫用戶或角色權(quán)限的語句,包括(grant,deny,revoke等)語句。在默認(rèn)狀態(tài)下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人員才有權(quán)力執(zhí)行DCLTCL - Transaction Control Language:事務(wù)控制語言,COMMIT - 保存已完成的工作,SAVEPOINT - 在事務(wù)中設(shè)置保存點(diǎn),可以回滾到此處,ROLLBACK - 回滾,SET TRANSACTION - 改變事務(wù)選項(xiàng)'''
#第十四章:并發(fā)編程
'''
新建態(tài)start()變就緒態(tài)
就緒態(tài)得到CPU變運(yùn)行態(tài),運(yùn)行態(tài)失去CPU變就緒態(tài)(CPU控制不關(guān)程序員事)
運(yùn)行態(tài)sleep()或IO阻塞或等待鎖或等待通知變阻塞態(tài)
阻塞態(tài)sleep()完或IO方法返回或獲得鎖或收到通知變就緒態(tài)
運(yùn)行態(tài)run()或target完成變死亡態(tài)(若中途Error或Exception也變死亡態(tài))
'''#創(chuàng)建線程
#第一種方式:直接使用Thread類(推薦)
import threading
def action(maxs):for j in range(maxs):print(threading.current_thread().getName() + " " + str(j))
for i in range(10):print(threading.current_thread().getName() + " " + str(i))if i == 3:t1 =threading.Thread(target=action,name='t1',args=(20,))t1.start()#必須調(diào)用start()才能把run方法變成線程執(zhí)行體,若調(diào)用run就是普通調(diào)用函數(shù)t2 =threading.Thread(target=action,name='t2',args=(20,))t2.start()#只有新建狀態(tài)的線程才能調(diào)用start方法轉(zhuǎn)換為就緒態(tài)
print('主線程執(zhí)行完成!')
#threading.Thread的參數(shù):
#group=None:線程所屬線程組
#target=None:線程要調(diào)度的目標(biāo)方法
#name=None:線程名字
#args=():傳入?yún)?shù)
#kwargs=None:指定字典傳入?yún)?shù)
#daemon=None:指定所構(gòu)建的線程是否為后臺線程
#第二種方式:繼承Threado在(不推薦)
import threading
class myThread(threading.Thread):def __init__(self,x): threading.Thread.__init__(self,target=self.go,name=x)#相當(dāng)于上一例的傳參self.j = 0def go(self):print('go')
'''
# 如果重寫run()方法作為線程執(zhí)行體,則會覆蓋上面的go函數(shù)def run(self): while self.j < 20:print(threading.current_thread().getName() + " " + str(self.j))self.j += 1
'''
for i in range(10):print(threading.current_thread().getName() + " " + str(i))if i == 9:ft1 = myThread('t1')ft1.start()ft2 = myThread('t2')ft2.start()
print('主線程執(zhí)行完成!')#join
import time
import threading
def action():time.sleep(2)for i in range(5):print(threading.current_thread().name+str(i)+'\n')
jt=threading.Thread(target=action, name="Join線程")
jt.start()
jt.join()#有參數(shù)timeout=None表示等待被join的最大時(shí)長
time.sleep(1)
print(threading.current_thread().name+'\n')#daemon thread后臺線程(全部前臺線程結(jié)束就會結(jié)束)
import threading
def action(max):# 定義后臺線程的線程執(zhí)行體與普通線程沒有任何區(qū)別time.sleep(1)for i in range(max):print(threading.current_thread().name + " " + str(i))
t = threading.Thread(target=action,args=(20,),daemon = True,name='后臺線程')
t.start()
time.sleep(1)
for i in range(10):print(threading.current_thread().name + " " + str(i))
# -----程序執(zhí)行到此處,前臺線程(主線程)結(jié)束,后臺線程也應(yīng)該隨之結(jié)束------#time
import time
for i in range(10):print("當(dāng)前時(shí)間: %s" % time.ctime())time.sleep(1)#同步鎖
import threading
import time
class Account:def __init__(self, account_no, balance):self.account_no = account_no #賬戶編號self._balance = balance #賬戶余額self.lock = threading.RLock()def draw(self, draw_amount):# 提供一個(gè)線程安全的draw()方法來完成取錢操作time.sleep(1)self.lock.acquire()#blocking=True,timeout=-1指定加鎖時(shí)間try:if self._balance>=draw_amount:#賬戶余額大于取錢數(shù)目self._balance-=draw_amount#修改余額print(threading.current_thread().name+"取錢成功,余額為:"+str(self._balance)+'\n',end='')else:print(threading.current_thread().name+"取錢失敗,余額為:"+str(self._balance)+'\n',end='')finally:self.lock.release()# 修改完成,釋放鎖
def draw(account, draw_amount):account.draw(draw_amount)# 直接調(diào)用account對象的draw()方法來執(zhí)行取錢操作
acct = Account("1234567" , 1000)
threading.Thread(name='甲', target=draw , args=(acct , 500)).start()
threading.Thread(name='乙', target=draw , args=(acct , 600)).start()
#LOCK與RLOCK
#Lock:基本鎖對象,每次鎖一次,其余鎖請求需等待鎖釋放后才能獲取
#RLock:可重入鎖,N次acquire就有N次release(推薦)#死鎖
import threading
import time
class A:def __init__(self):self.lock = threading.RLock()def foo(self, b):try:self.lock.acquire()print("當(dāng)前線程名: " + threading.current_thread().name+ " 進(jìn)入了A實(shí)例的foo()方法" ) # ①time.sleep(0.2)print("當(dāng)前線程名: " + threading.current_thread().name+ " 企圖調(diào)用B實(shí)例的last()方法") # ③b.last()finally:self.lock.release()def last(self):try:self.lock.acquire()finally:self.lock.release()
class B:def __init__(self):self.lock = threading.RLock()def bar(self, a):try:self.lock.acquire()print("當(dāng)前線程名: " + threading.current_thread().name+ " 進(jìn)入了B實(shí)例的bar()方法" ) # ②time.sleep(0.2)print("當(dāng)前線程名: " + threading.current_thread().name+ " 企圖調(diào)用A實(shí)例的last()方法") # ④a.last()finally:self.lock.release()def last(self):try:self.lock.acquire()finally:self.lock.release()
a = A()
b = B()
def init():threading.current_thread().name = "主線程"a.foo(b)
def action():threading.current_thread().name = "副線程"b.bar(a)
threading.Thread(target=action).start()
init()#condition
#acquire/release:就是關(guān)聯(lián)lock的acquire/release
#wait:當(dāng)前進(jìn)程進(jìn)入condition等待池等待通知并釋放鎖
#notify:喚醒在condition等待池的單個(gè)線程(任意)
#notify_all:喚醒在condition等待池的全部線程
import threading
import time
class Account:def __init__(self, account_no, balance):self.account_no = account_noself._balance = balanceself.cond = threading.Condition()self._flag = False# 定義代表是否已經(jīng)存錢的旗標(biāo)def draw(self, draw_amount):time.sleep(0.5)self.cond.acquire()# 加鎖,相當(dāng)于調(diào)用Condition綁定的Lock的acquire()try:if not self._flag:# 如果self._flag為假,表明賬戶中還沒有人存錢進(jìn)去,取錢方法阻塞self.cond.wait()else:self._balance -= draw_amountprint(threading.current_thread().name+"取錢"+str(draw_amount)+" 賬戶余額"+str(self._balance)+'\n',end='')self._flag = False# 將標(biāo)識賬戶是否已有存款的旗標(biāo)設(shè)為Falseself.cond.notify_all()# 喚醒其他線程finally:# 使用finally塊來釋放鎖self.cond.release()def deposit(self, deposit_amount):time.sleep(1)self.cond.acquire()# 加鎖,相當(dāng)于調(diào)用Condition綁定的Lock的acquire()try:if self._flag:# 如果self._flag為真,表明賬戶中已有人存錢進(jìn)去,存錢方法阻塞self.cond.wait()else:self._balance += deposit_amountprint(threading.current_thread().name+"存款"+str(deposit_amount)+" 賬戶余額"+str(self._balance)+'\n',end='')self._flag = True# 將表示賬戶是否已有存款的旗標(biāo)設(shè)為Trueself.cond.notify_all()# 喚醒其他線程finally:# 使用finally塊來釋放鎖self.cond.release()
def draw_many(account, draw_amount, maxs):#模擬重復(fù)max次執(zhí)行取錢操作for i in range(maxs):account.draw(draw_amount)
def deposit_many(account, deposit_amount, maxs):#模擬重復(fù)max次執(zhí)行存款操作for i in range(maxs):account.deposit(deposit_amount)
acct = Account("1234567" , 0)# 創(chuàng)建一個(gè)賬戶
threading.Thread(name="取錢者", target=draw_many,args=(acct, 800, 10)).start()
threading.Thread(name="存款者甲", target=deposit_many,args=(acct , 800, 10)).start()
threading.Thread(name="存款者乙", target=deposit_many,args=(acct , 800, 10)).start()
threading.Thread(name="存款者丙", target=deposit_many,args=(acct , 800, 10)).start()#queue
'''
queue.Queue(maxsize=0):FIFO
queue.LifoQueue(maxsize=0):LIFO
PriorityQueue(maxsize=0):優(yōu)先隊(duì)列
Queue.qsize():隊(duì)列元素個(gè)數(shù)
Queue.empty():隊(duì)列是否為空
Queue.full():隊(duì)列是否為滿
Queue.put(item,block=True,timeout=None):入隊(duì)
Queue.put_nowait(item):入隊(duì)且不阻塞(入不了就丟棄)
Queue.get(item,block=True,timeout=None):出隊(duì)
Queue.get_nowait(item):出隊(duì)且不阻塞(沒元素就是空)
'''
import threading
import time
import queue
ans=[]
def product(bq):for i in range(3):t=threading.current_thread().name+"'s no."+str(i)bq.put(t)# 嘗試放入元素,如果隊(duì)列已滿,則線程被阻塞ans.append(threading.current_thread().name+"第%d次生產(chǎn)%s"%(i,t))
def consume(bq):for i in range(9):t = bq.get()# 嘗試取出元素,如果隊(duì)列已空,則線程被阻塞ans.append(threading.current_thread().name+"第%d次消費(fèi)%s"%(i,t))
bq = queue.Queue(maxsize=1)# 創(chuàng)建一個(gè)容量為1的Queue
threading.Thread(target=product,name='a',args=(bq, )).start()# 啟動3個(gè)生產(chǎn)者線程
threading.Thread(target=product,name='b',args=(bq, )).start()
threading.Thread(target=product,name='c',args=(bq, )).start()
threading.Thread(target=consume,name='x',args=(bq, )).start()# 啟動一個(gè)消費(fèi)者線程
time.sleep(1)#等待上面的線程跑完
print(ans)#我發(fā)現(xiàn)不用上面的ans而是直接print會十分混亂!#event
#is_set():返回內(nèi)部旗標(biāo)是否為true
#set():設(shè)內(nèi)部旗標(biāo)為true
#clear():設(shè)內(nèi)部旗標(biāo)為false,后面常接wait
#wait(timeout=None):等待內(nèi)部旗標(biāo)為false
import threading
import time
event = threading.Event()
def cal(name):print(name+'正式等待'+'\n',end='')event.wait()print(name+'正式計(jì)算'+'\n',end='')
threading.Thread(target=cal, args=('甲', )).start()
threading.Thread(target=cal, args=("乙", )).start()
time.sleep(0.1)
print('主線程發(fā)出事件')
time.sleep(0.1)
event.set()#線程池:需要創(chuàng)建大量生存期很短暫的線程時(shí)使用
#result得到結(jié)果
from concurrent.futures import ThreadPoolExecutor
import threading
import time
def action(max):#定義線程任務(wù)是累加和my_sum = 0for i in range(max):print(threading.current_thread().name + ' ' + str(i)+'\n',end='')my_sum += ireturn my_sum
pool = ThreadPoolExecutor(max_workers=2)# 創(chuàng)建一個(gè)包含2條線程的線程池
future1 = pool.submit(action, 10)# 向線程池提交一個(gè)task, 10會作為action()函數(shù)的參數(shù)
future2 = pool.submit(action, 20)# 向線程池提交一個(gè)task, 20會作為action()函數(shù)的參數(shù)
print(str(future1.done())+'\n',end='')# 判斷future1代表的任務(wù)是否結(jié)束
time.sleep(0.1)
print(future2.done())# 判斷future2代表的任務(wù)是否結(jié)束
print(future1.result())# 查看future1代表的任務(wù)返回的結(jié)果(如未返回會阻塞主線程)
print(future2.result())# 查看future2代表的任務(wù)返回的結(jié)果
pool.shutdown()# 關(guān)閉線程池
print('--------------')
#注意:最后四行一定是True,45,190,-------因?yàn)榇嬖谧枞P(guān)系!
#add_done_callback:用法是調(diào)用回調(diào)函數(shù),再調(diào)用result就可不阻塞主線程且何時(shí)執(zhí)行完何時(shí)輸出
from concurrent.futures import ThreadPoolExecutor
import threading
def action(max):# 定義一個(gè)準(zhǔn)備作為線程任務(wù)的函數(shù)my_sum = 0for i in range(max):print(threading.current_thread().name + ' ' + str(i)+'\n',end='')my_sum += ireturn my_sum
with ThreadPoolExecutor(max_workers=2) as pool:# 用with寫就不用手動關(guān)了future1 = pool.submit(action, 10)# 向線程池提交一個(gè)task, 50會作為action()函數(shù)的參數(shù)future2 = pool.submit(action, 20)# 向線程池再提交一個(gè)task, 100會作為action()函數(shù)的參數(shù)def get_result(future):print(str(future.result())+'\n',end='')future1.add_done_callback(get_result)# 為future1添加線程完成的回調(diào)函數(shù)future2.add_done_callback(get_result)# 為future2添加線程完成的回調(diào)函數(shù)print('--------------'+'\n',end='')
#map
from concurrent.futures import ThreadPoolExecutor
import threading
def action(max):# 定義一個(gè)準(zhǔn)備作為線程任務(wù)的函數(shù)my_sum = 0for i in range(max):print(threading.current_thread().name + ' ' + str(i)+'\n',end='')my_sum += ireturn my_sum
with ThreadPoolExecutor(max_workers=4) as pool:# 創(chuàng)建一個(gè)包含4條線程的線程池results = pool.map(action, (10, 20, 30))#后面元組3元素故程序啟動3條線程來執(zhí)行action函數(shù)print('--------------'+'\n',end='')for r in results:print(str(r)+'\n',end='')#local(其實(shí)在線程執(zhí)行函數(shù)里面定義局部變量即可)
import threading
from concurrent.futures import ThreadPoolExecutor
mydata = threading.local()# 定義線程局部變量:即每個(gè)線程都復(fù)制一個(gè)
def action (max):for i in range(max):try:mydata.x += iexcept:mydata.x = iprint('%s mydata.x的值為: %d' %(threading.current_thread().name, mydata.x)+'\n',end='')
with ThreadPoolExecutor(max_workers=2) as pool:pool.submit(action , 5)pool.submit(action , 10)#timerfrom threading import Timer
def hello():print("hello, world")
t=Timer(10.0, hello)# 指定10秒后執(zhí)行hello函數(shù)
t.start()#定時(shí)器開始
from threading import Timer
import time
count = 0# 定義總共輸出幾次的計(jì)數(shù)器
def print_time():print("當(dāng)前時(shí)間:%s" % time.ctime())global t, countcount += 1if count < 10:# 如果count小于10,開始下一次調(diào)度t=Timer(1, print_time)#定時(shí)器要重新裝載t.start()
t = Timer(1, print_time)# 指定1秒后執(zhí)行print_time函數(shù)
t.start()#任務(wù)調(diào)度
import sched, time
s = sched.scheduler()# 定義線程調(diào)度器
def print_time(name='default'):# 定義被調(diào)度的函數(shù)print("%s 的時(shí)間: %s" % (name, time.ctime()))
print('主線程:', time.ctime())
s.enter(10, 1, print_time)# 指定10秒之后執(zhí)行print_time函數(shù)
s.enter(5, 2, print_time, argument=('位置參數(shù)',))# 指定5秒之后執(zhí)行print_time函數(shù),優(yōu)先級為2
s.enter(5, 1, print_time, kwargs={'name': '關(guān)鍵字參數(shù)'})# 指定5秒之后執(zhí)行print_time函數(shù),優(yōu)先級為1
s.run()# 執(zhí)行調(diào)度的任務(wù),會阻塞主線程
print('主線程:', time.ctime())#多進(jìn)程
#fork
import os#在windows系統(tǒng)上無效
print('父進(jìn)程(%s)開始執(zhí)行' % os.getpid())
pid = os.fork()# 開始fork一個(gè)子進(jìn)程,下面代碼都會被兩個(gè)進(jìn)程執(zhí)行
print('進(jìn)程進(jìn)入:%s' % os.getpid())
if pid == 0:# 如果pid為0,表明是子進(jìn)程print('子進(jìn)程,其ID為 (%s), 父進(jìn)程ID為 (%s)' % (os.getpid(), os.getppid()))
else:print('我 (%s) 創(chuàng)建的子進(jìn)程ID為 (%s).' % (os.getpid(), pid))
print('進(jìn)程結(jié)束:%s' % os.getpid())#Process(我的編譯器好像有問題,開不了子進(jìn)程)
#run重新進(jìn)程執(zhí)行體
#start啟動進(jìn)程
#join當(dāng)前進(jìn)程等被join進(jìn)程執(zhí)行完才能往下執(zhí)行,name設(shè)置訪問進(jìn)程的名字
#is_alive()進(jìn)程是否活著
#daemon進(jìn)程是否是后臺狀態(tài)
#pid進(jìn)程ID
#authkery進(jìn)程授權(quán)key
#terminate()中斷進(jìn)程
import multiprocessing
import os
def action(maxs):for i in range(maxs):print("(%s)子進(jìn)程(父進(jìn)程:(%s)):%d" %(os.getpid(), os.getppid(), i))
if __name__ == '__main__':# 下面是主程序(也就是主進(jìn)程)for i in range(10):print("(%s)主進(jìn)程: %d" % (os.getpid(), i))if i == 2:mp=multiprocessing.Process(target=action,args=(10,))mp.start()mp.join()print('主進(jìn)程執(zhí)行完成!')
import multiprocessing
import os
class MyProcess(multiprocessing.Process):def __init__(self, max):self.max = maxsuper().__init__()def run(self):# 重寫run()方法作為進(jìn)程執(zhí)行體for i in range(self.max):print("(%s)子進(jìn)程(父進(jìn)程:(%s)):%d"%(os.getpid(),os.getppid(),i))
if __name__ == '__main__':for i in range(10):# 下面是主程序(也就是主進(jìn)程)print("(%s)主進(jìn)程: %d" % (os.getpid(), i))if i == 2:mp=MyProcess(10)mp.start()mp.join()print('主進(jìn)程執(zhí)行完成!')#Context和啟動進(jìn)程的方式
import multiprocessing#fork在UNIX
def foo(q):q.put('Python')
if __name__ == '__main__':multiprocessing.set_start_method('fork') # 設(shè)置使用fork方式啟動進(jìn)程q = multiprocessing.Queue()mp = multiprocessing.Process(target=foo, args=(q, )) # 創(chuàng)建進(jìn)程mp.start() # 啟動進(jìn)程print(q.get()) # 獲取隊(duì)列中的消息
import multiprocessing#spawn在WIN
def foo(q):q.put('Python!')
if __name__ == '__main__':ctx = multiprocessing.get_context('spawn') # 使用spawn方式啟動進(jìn)程并獲取Context對象q = ctx.Queue()# 接下來就可用Context對象來代替mutliprocessing模塊了mp = ctx.Process(target=foo, args=(q, )) # 創(chuàng)建進(jìn)程mp.start() # 啟動進(jìn)程print(q.get()+'abc') # 獲取隊(duì)列中的消息 #進(jìn)程池(唯一BUG:子進(jìn)程不能輸出到控制臺)
import multiprocessing
import time
def action(name='default'):print(name)time.sleep(1)
if __name__ == '__main__':pool = multiprocessing.Pool(processes=4)# 創(chuàng)建包含4條進(jìn)程的進(jìn)程池pool.apply_async(action)# 將action分3次提交給進(jìn)程池pool.apply_async(action, args=('位置參數(shù)', ))pool.apply_async(action, kwds={'name': '關(guān)鍵字參數(shù)'})pool.close()pool.join()print('主進(jìn)程結(jié)束')
import multiprocessing
def action(max):my_sum = 0for i in range(max):print(i)#老樣子,子進(jìn)程不能輸出到控制臺my_sum += ireturn my_sum
if __name__ == '__main__':with multiprocessing.Pool(processes=4) as pool:# 創(chuàng)建一個(gè)包含4條進(jìn)程的進(jìn)程池results = pool.map(action, (50, 100, 150))for r in results:print(r)#隊(duì)列通信
import multiprocessing
def f(q):print('(%s) 進(jìn)程開始放入數(shù)據(jù)...' % multiprocessing.current_process().pid)q.put('Python')
if __name__ == '__main__':q = multiprocessing.Queue()# 創(chuàng)建進(jìn)程通信的Queuep = multiprocessing.Process(target=f, args=(q,))# 創(chuàng)建子進(jìn)程p.start()# 啟動子進(jìn)程p.join()print('(%s) 進(jìn)程開始取出數(shù)據(jù)...' % multiprocessing.current_process().pid)print(q.get()) # 取出數(shù)據(jù) Python#管道通信
import multiprocessing
def f(conn):print('(%s) 進(jìn)程開始發(fā)送數(shù)據(jù)...' % multiprocessing.current_process().pid)conn.send('Python')# 使用conn發(fā)送數(shù)據(jù)
if __name__ == '__main__':parent_conn, child_conn = multiprocessing.Pipe()# 創(chuàng)建Pipe,該函數(shù)返回兩個(gè)PipeConnection對象p = multiprocessing.Process(target=f, args=(child_conn, ))# 創(chuàng)建子進(jìn)程p.start()# 啟動子進(jìn)程print('(%s) 進(jìn)程開始接收數(shù)據(jù)...' % multiprocessing.current_process().pid)print(parent_conn.recv()) # 通過conn讀取數(shù)據(jù) Pythonp.join()
#第十五章:網(wǎng)絡(luò)編程
'''基本模塊
傳輸層
socket------------重點(diǎn)(TCP/UDP服務(wù)器與客戶端通訊)
asyncore
asynchat
應(yīng)用層
email
mailbox
mailcap
ftplib
httplib
imaplib
nntplib
smtplib------------重點(diǎn)(發(fā)郵件)
poplib-------------重點(diǎn)(收郵件)
telnetlib
urllib-------------重點(diǎn)(分析網(wǎng)址內(nèi)容,分析網(wǎng)頁內(nèi)容,cookie)
其他
xmlrpc,xmlrpc.server,xmlrpc.client
cgi
'''#urllib
#urllib.request:open and read URL
#urllib.error:catch error
#urllib.parse:解析URL
#urllib.robotparser解析robots.txt文件
from urllib.parse import *#分析網(wǎng)址內(nèi)容
result = urlparse('http://www.crazyit.org:80/index.php;yeeku?name=fkit#frag')# 解析URL字符串
print(result)# 下面通過屬性名和索引來獲取URL的各部分
print('scheme體系:', result.scheme, result[0])
print('主機(jī)和端口:', result.netloc, result[1])
print('主機(jī):', result.hostname)
print('端口:', result.port)
print('資源路徑:', result.path, result[2])
print('參數(shù):', result.params, result[3])
print('查詢字符串:', result.query, result[4])
print('fragment碎片:', result.fragment, result[5])
print(result.geturl())
print('---a--------------')
result = urlunparse(('http','www.crazyit.org:80','index.php','yeeku','name=fkit','frag'))
print('URL為:', result)
print('---b--------------')
result = urlparse('//www.crazyit.org:80/index.php')# 解析以//開頭的URL
print('scheme:', result.scheme, result[0])
print('主機(jī)和端口:', result.netloc, result[1])
print('資源路徑:', result.path, result[2])
print('---c--------------')
result = urlparse('www.crazyit.org/index.php')
print('scheme:', result.scheme, result[0])# 解析沒有scheme,也沒有以雙斜線(//)開頭的URL
print('主機(jī)和端口:', result.netloc, result[1])
print('資源路徑:', result.path, result[2])# 從開頭部分開始就會被當(dāng)成資源路徑
print('---d--------------')
result = parse_qs('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')# 解析查詢字符串,返回dict
print(result)
result = parse_qsl('name=fkit&name=%E7%96%AF%E7%8B%82java&age=12')# 解析查詢字符串,返回list
print(result)
print(urlencode(result))# 將列表格式的請求參數(shù)恢復(fù)成請求參數(shù)字符串
print('---e--------------')
# 被拼接URL以多少個(gè)/開頭就會中踢掉后面多少個(gè)/段
result = urljoin('http://www.crazyit.org/users/login.html', 'help.html')
print(result) # http://www.crazyit.org/users/help.html
result = urljoin('http://www.crazyit.org/users/login.html', 'book/list.html')
print(result) # http://www.crazyit.org/users/book/list.html
result = urljoin('http://www.crazyit.org/users/login.html', '/help.html')# 被拼接URL以斜線(代表根路徑path)開頭
print(result) # http://www.crazyit.org/help.html
result = urljoin('http://www.crazyit.org/users/login.html', '//help.html')# 被拼接URL以雙斜線(代表絕對URL)開頭
print(result) # http://help.html#urlopen(需要先在本地部署web應(yīng)用,不然就改網(wǎng)址)
from urllib.parse import *#下面三例是不提交data,提交data-str及dict
with urlopen(url='https://www.baidu.com/') as f:print(f.read().decode('utf-8'))# 讀取服務(wù)器全部響應(yīng)
with urlopen(url='https://www.baidu.com/',data='測試數(shù)據(jù)'.encode('utf-8')) as f:print(f.read().decode('utf-8'))# 讀取服務(wù)器全部響應(yīng)
params = urllib.parse.urlencode({'name': '瘋狂軟件', 'password': '123888'}).encode('utf-8')
with urlopen("https://www.baidu.com/", data=params) as f:# 使用data指定請求參數(shù)print(f.read().decode('utf-8'))import requests #需求(分析網(wǎng)頁內(nèi)容,常結(jié)合re匹配要找的串)
from bs4 import BeautifulSoup #BeautifulSoup庫解析代碼
url='http://www.wsbookshow.com'#定義網(wǎng)址
html=requests.get(url) #引用需求庫的獲取網(wǎng)址HTML文件
html.encoding="GBK" #編碼是GBK
soup=BeautifulSoup(html.text,'html.parser')#分析文件標(biāo)簽劃分
print(soup)
#htmllist=html.text.splitlines() #把文本分隔
#for row in htmllist:print(row)
links=soup.find_all(["a","img"])#得到a,img兩個(gè)標(biāo)簽的內(nèi)容
for link in links:#逐個(gè)連接掃一次href=link.get("href")#獲取此連接中href關(guān)鍵字內(nèi)容if href!=None and href.startswith("http://"):#HREF以http://開頭print(href)#輸出#爬蟲網(wǎng)站中的圖片
import requests,os
from bs4 import BeautifulSoup
from urllib.request import urlopen
url='http://www.tooopen.com/img/87.aspx' #定義網(wǎng)址
html=requests.get(url) #獲取HTML文件
html.encoding="utf-8" #定義編碼方式
sp=BeautifulSoup(html.text,'html.parser') #解釋
images_dir="images/" #定義路徑
if not os.path.exists(images_dir): #如果路徑不存在os.mkdir(images_dir) #創(chuàng)建路徑
all_links=sp.find_all(['a','img']) #尋獲取所有A與IMG標(biāo)簽中的內(nèi)容
for link in all_links:#遍歷每一個(gè)標(biāo)簽內(nèi)容src=link.get('src')#獲得標(biāo)簽內(nèi)容中含SRC的串href=link.get('href')#獲得標(biāo)簽內(nèi)容中含HREF的串a(chǎn)ttrs=[href,src]#定義一個(gè)列表,兩個(gè)元素分別是兩個(gè)串for attr in attrs:#遍歷一次,這里要注意一個(gè)標(biāo)簽里可以有多個(gè)串含SRC或HREFif attr!=None and ('.jpg' in attr or '.png' in attr):#如果非空且含JPG與PNG后綴full_path=attr#讀回其路徑filename=full_path.split('/')[-1]#文件名是按/劃分的子串的倒數(shù)第一個(gè)ext=filename.split('.')[-1]#后綴名是按.劃分的子串中的倒數(shù)第一個(gè)filename=filename.split('.')[-2]#文件名是按.劃分的子串中的到數(shù)第二個(gè)if 'jpg' in ext: filename=filename+'.jpg'#文件名加上后綴else: filename=filename+'.png'#文件名加上后綴print(filename)#輸出文件名try:#嘗試image=urlopen(full_path)#通過完整路徑獲取圖片f=open(os.path.join(images_dir,filename),'wb')#wb:以二進(jìn)制寫模式打開本地文件(由路徑知其實(shí)是圖片)f.write(image.read())#寫入文件(就是復(fù)制圖片)f.close()#關(guān)閉except:#失敗print("error") #報(bào)錯(cuò)#爬蟲PM2.5實(shí)例
from bs4 import BeautifulSoup
import requests
url1='http://www.PM25X.com/'
html=requests.get(url1)
sp1=BeautifulSoup(html.text,'html.parser')
city=sp1.find("a",{"title":"北京PM2.5"})#find返回匹配結(jié)果的第一個(gè)元素
print(city)#輸出
citylink=city.get("href")#獲取href關(guān)鍵字的內(nèi)容
print(citylink)#輸出
url2=url1+citylink#由此可以得到子網(wǎng)頁的網(wǎng)址
print(url2)#get the suburl!
html2=requests.get(url2)#獲HTML
sp2=BeautifulSoup(html2.text,'html.parser')#分析
data1=sp2.select(".aqivalue")#選擇
pm25=data1[0].text#得第0個(gè)元素的值
print("now Beijing's PM2.5 is: "+pm25)
'''
find_all(name,attrs,recursive,text,**kwargs)根據(jù)標(biāo)簽名/屬性/內(nèi)容查找文檔,返回一個(gè)列表
text結(jié)果返回的是查到的所有的text='***'的文本
find(name,attrs,recursive,text,**kwargs)返回的匹配結(jié)果的第一個(gè)元素
get_text()可以獲取文本內(nèi)容
attrs可以傳入字典的方式來查找標(biāo)簽,這里有個(gè)特殊的就是class,因?yàn)閏lass在python中是特殊的字段,所以如果想要查找class相關(guān)的可以更改attrs={'class_':'element'}或者soup.find_all('',{"class":"element}),特殊的標(biāo)簽屬性可以不寫attrs,例如id
'''#cookie保存(沒服務(wù)器運(yùn)行不了)
from urllib.request import *
import http.cookiejar, urllib.parse
cookie_jar = http.cookiejar.MozillaCookieJar('a.txt')# 以指定文件創(chuàng)建CookieJar對象,對象將可以把cookie保存在文件中
cookie_processor = HTTPCookieProcessor(cookie_jar)# 創(chuàng)建HTTPCookieProcessor對象
opener = build_opener(cookie_processor)# 創(chuàng)建OpenerDirector對象
user_agent = r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36' \r' (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'# 定義模擬Chrome瀏覽器的user_agent
headers = {'User-Agent':user_agent, 'Connection':'keep-alive'}# 定義請求頭
#-------------下面代碼發(fā)送登錄的POST請求----------------
params = {'name':'crazyit.org', 'pass':'leegang'}# 定義登錄系統(tǒng)的請求參數(shù)
postdata = urllib.parse.urlencode(params).encode()
request = Request('http://localhost:8888/test/login.jsp',data = postdata, headers = headers)# 創(chuàng)建向登錄頁面發(fā)送POST請求的Request
response = opener.open(request)# 使用OpenerDirector發(fā)送POST請求
print(response.read().decode('utf-8'))
cookie_jar.save(ignore_discard=True, ignore_expires=True) # 將cookie信息寫入磁盤文件
#-------------下面代碼發(fā)送訪問被保護(hù)資源的GET請求----------------
request = Request('http://localhost:8888/test/secret.jsp',headers=headers)# 創(chuàng)建向"受保護(hù)頁面"發(fā)送GET請求的Request
response = opener.open(request)
print(response.read().decode())#cookie加載(沒服務(wù)器運(yùn)行不了)
from urllib.request import *
import http.cookiejar, urllib.parse
cookie_jar = http.cookiejar.MozillaCookieJar('a.txt')# 以指定文件創(chuàng)建CookieJar對象,對象將可以把cookie保存在文件中
cookie_jar.load('a.txt',ignore_discard=True,ignore_expires=True)# 直接加載a.txt中的Cookie信息
for item in cookie_jar:# 遍歷a.txt中保存的cookie信息print('Name ='+ item.name)print('Value ='+ item.value)
cookie_processor = HTTPCookieProcessor(cookie_jar)# 創(chuàng)建HTTPCookieProcessor對象
opener = build_opener(cookie_processor)# 創(chuàng)建OpenerDirector對象
user_agent = r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36' \r' (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'# 定義模擬Chrome瀏覽器的user_agent
headers = {'User-Agent':user_agent, 'Connection':'keep-alive'}# 定義請求頭
request = Request('http://localhost:8888/test/secret.jsp',headers=headers)# 創(chuàng)建向"受保護(hù)頁面"發(fā)送GET請求的Request
response = opener.open(request)
print(response.read().decode())'''
下面是本章重點(diǎn),涉及編碼問題
首先重申一下上一章的內(nèi)容
二、字符串前加 b
b" "前綴表示后面字符串是bytes類型
網(wǎng)絡(luò)編程中,服務(wù)器和瀏覽器只認(rèn)bytes類型數(shù)據(jù)
在 Python3 中,bytes 和 str 的互相轉(zhuǎn)換方式是
str.encode('utf-8')
bytes.decode('utf-8')
'''
with open('utf-8_test.txt','rb+',True) as f:print(f.read().decode('utf-8'))#得到字符串注意編譯器默認(rèn)就是uft-8編碼
with open('utf-8_test.txt','rb+',True) as f:print(f.read())#得到字節(jié)類對象注意漢字是用24位二進(jìn)制表示,如‘我’是\xe9\x99\x88#UDP服務(wù)器端
import socket
s = socket.socket(type=socket.SOCK_DGRAM)#UDP
s.bind(('127.0.0.1',30000))#將該socket綁定到本機(jī)的指定IP和端口(注意這是本機(jī)IP與端口)
for i in range(3):#采用循環(huán)接收數(shù)據(jù),此處設(shè)置接收三次就要結(jié)束連接data,addr=s.recvfrom(4096)#讀取s中的數(shù)據(jù)(最大4KB)的數(shù)據(jù)及發(fā)送地址(即源機(jī)IP與端口)if data.decode('utf-8')=='exit':break#如果是退出就斷開連接else: print(data.decode('utf-8'))#否則將接收到的內(nèi)容轉(zhuǎn)換成字符串后輸出s.sendto('I love you.'.encode('utf-8'),addr)#將數(shù)據(jù)報(bào)發(fā)送給addr地址
s.close()
#UDP客戶端
import socket
s=socket.socket(type=socket.SOCK_DGRAM)#創(chuàng)建基于UDP協(xié)議的socket
while True:line=input('')#不斷地讀取鍵盤輸入s.sendto(line.encode('utf-8'),("127.0.0.1",30000))#往目的IP與PORT發(fā)送數(shù)據(jù)報(bào)if line=='exit':breakprint(s.recv(4096).decode('utf-8'))#讀取socket中的數(shù)據(jù),最大4KB
s.close()
#UDP多點(diǎn)廣播(主客端一樣的代碼,SENDERPORT與TARGETPORT改同一個(gè)端口即可多點(diǎn)互通,下面用兩個(gè)端口是因?yàn)橹挥幸慌_機(jī)不能同一個(gè)端口綁定兩次)
import socket, threading
SENDERIP = '127.0.0.1'# 定義本機(jī)IP地址
SENDERPORT = 30030# 定義本地發(fā)送端口,也是本機(jī)接收信息的端口
TARGETPORT = 30031# 定義目的接收端口,也是目的發(fā)送信息的端口
MYGROUP = '230.0.0.1'# 定義本程序的多點(diǎn)廣播IP地址
s = socket.socket(type=socket.SOCK_DGRAM)# 通過type屬性指定創(chuàng)建基于UDP協(xié)議的socket
s.bind(('0.0.0.0', SENDERPORT))#將該socket綁定到0.0.0.0的虛擬IP,在多點(diǎn)廣播組內(nèi)只要端口對就能接收
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 64)# 設(shè)置廣播消息的TTL(Time-To-Live)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 設(shè)置允許多點(diǎn)廣播使用相同的端口
status=s.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,socket.inet_aton(MYGROUP)+socket.inet_aton(SENDERIP))#將socket進(jìn)入廣播組
def read_socket(sock):while True:#多線程循環(huán)執(zhí)行體,從socket讀取數(shù)據(jù)并輸出data = sock.recv(2048)#讀回來的data是字節(jié)類對象if data.decode('utf-8')=='exit':break#轉(zhuǎn)成str才可以比較print("\n收到的信息:", data.decode('utf-8'))
t=threading.Thread(target=read_socket, args=(s, ))
t.start()# 以read_socket作為target啟動多線程
while True:#主線程循環(huán)執(zhí)行體,采用循環(huán)不斷讀取鍵盤輸入,并輸出到socket中l(wèi)ine=input("發(fā)送的信息: ")#輸入的line就是字符串類型s.sendto(line.encode('utf-8'),(MYGROUP, TARGETPORT))#多點(diǎn)廣播輸出到廣播IP中if line=='exit':break#可以直接比較
t.join()
import time
time.sleep(0.1)
s.close()#TCP例一:基本通訊
#server
import socket
import threading
ss = socket.socket()#創(chuàng)建socket對象
ss.bind(('192.168.101.9', 30003))#將socket綁定到本機(jī)IP和端口
ss.listen()#服務(wù)端開始監(jiān)聽來自客戶端的連接
def server_target(s): #采用循環(huán)不斷地從socket中讀取客戶端發(fā)送過來的數(shù)據(jù)for i in range(3): #改成while True:可以一直死循環(huán)content = s.recv(2048).decode('utf-8')#獲得信息內(nèi)容print(content)s.send(content.encode('utf-8'))
for i in range(1): #改成while True:可以一直死循環(huán)s,addr=ss.accept() #此行代碼會阻塞,將一直等待別人的連接threading.Thread(target=server_target, args=(s,)).start()#每當(dāng)客戶端連接后啟動一個(gè)線程為該客戶端服務(wù)
#client
import socket
import threading
s = socket.socket() #創(chuàng)建socket對象
s.connect(('192.168.101.9', 30003)) #連接遠(yuǎn)程主機(jī)
def read_from_server(s): #客戶端啟動線程不斷地讀取來自服務(wù)器的數(shù)據(jù)for i in range(3): #改成while True:可以一直死循環(huán)print(s.recv(2048).decode('utf-8'))
threading.Thread(target=read_from_server, args=(s, )).start()
for i in range(3): #改成while True:可以一直死循環(huán)line=input('')if line=='exit':breaks.send(line.encode('utf-8'))#將用戶的鍵盤輸入內(nèi)容寫入socket
#補(bǔ)充一:要實(shí)現(xiàn)保存每個(gè)socket對應(yīng)的數(shù)據(jù),如用戶名及密碼,可用dict或創(chuàng)建新的類來維護(hù)
#補(bǔ)充二:要實(shí)現(xiàn)帳號密碼登陸的,只需要在多線程執(zhí)行體的循環(huán)前加上兩次帳號密碼通迅即可
#補(bǔ)充三、要實(shí)現(xiàn)TCP的多人聊天廣播,每個(gè)群用一個(gè)列表(元素類型socket)來維護(hù)即可,發(fā)送到群就改為列表里逐個(gè)socket發(fā)#TCP例二:半關(guān)閉的socket
#server
import socket
s = socket.socket() # 創(chuàng)建socket對象
s.bind(('192.168.101.9', 30000)) # 將socket綁定到本機(jī)IP和端口
s.listen() # 服務(wù)端開始監(jiān)聽來自客戶端的連接
skt, addr = s.accept() #每當(dāng)接收到客戶端socket的請求時(shí),該方法返回對應(yīng)的socket和遠(yuǎn)程地址
skt.send("服務(wù)器的第一行數(shù)據(jù)".encode('utf-8'))
skt.send("服務(wù)器的第二行數(shù)據(jù)".encode('utf-8'))
skt.shutdown(socket.SHUT_WR) #關(guān)閉socket的輸出,但仍可以接受數(shù)據(jù),相當(dāng)于發(fā)送空串
while True:line = skt.recv(2048).decode('utf-8')# 從socket讀取數(shù)據(jù)if line is None:breakprint(line)
skt.close()
s.close()
#client
import socket
s = socket.socket()# 創(chuàng)建socket對象
s.connect(('192.168.101.9', 30000))# 連接遠(yuǎn)程主機(jī)
while True:line = s.recv(2048).decode('utf-8') #從socket讀取數(shù)據(jù)if line is None:break #讀到空就breakprint(line)
s.send("客戶端的第一行數(shù)據(jù)".encode('utf-8'))
s.send("客戶端的第二行數(shù)據(jù)".encode('utf-8'))
s.close()#相當(dāng)于發(fā)送空串#TCP例三:非阻塞讀selectors
#好處:設(shè)置了監(jiān)聽事件后,不用死循環(huán)!#server
import selectors,socket,time
sel = selectors.DefaultSelector()# 創(chuàng)建默認(rèn)的selectors對象
def read(skt, mask):# 負(fù)責(zé)監(jiān)聽“有數(shù)據(jù)可讀”事件的函數(shù)try:data = skt.recv(1024)# 讀取數(shù)據(jù)if data:for s in socket_list:# 將讀取的數(shù)據(jù)采用循環(huán)向每個(gè)socket發(fā)送一次s.send(data) # Hope it won't blockelse:# 如果該socket已被對方關(guān)閉,關(guān)閉該socket,并從socket_list列表中刪除print('關(guān)閉', skt)sel.unregister(skt)skt.close()socket_list.remove(skt)except:# 如果捕捉到異常, 將該socket關(guān)閉,并從socket_list列表中刪除print('關(guān)閉', skt)sel.unregister(skt)skt.close()socket_list.remove(skt)
socket_list = []
def accept(sock, mask):# 負(fù)責(zé)監(jiān)聽“客戶端連接進(jìn)來”事件的函數(shù)conn, addr = sock.accept()socket_list.append(conn)# 使用socket_list保存代表客戶端的socketconn.setblocking(False)sel.register(conn, selectors.EVENT_READ, read)#使用sel為conn的EVENT_READ事件注冊read監(jiān)聽函數(shù)
sock = socket.socket()
sock.bind(('192.168.101.9', 30000))
sock.listen()
sock.setblocking(False) #設(shè)置該socket是非阻塞的
sel.register(sock, selectors.EVENT_READ, accept)#使用sel為sock的EVENT_READ事件注冊accept監(jiān)聽函數(shù)
while True: #采用死循環(huán)不斷提取sel的事件time.sleep(1) #這一秒可以去做其他的事情events = sel.select() #回顧過去一秒監(jiān)聽到的事件for key, mask in events: #逐個(gè)事件調(diào)取對應(yīng)的監(jiān)聽函數(shù)callback = key.data #key的data屬性獲取為該事件注冊的監(jiān)聽函數(shù)callback(key.fileobj, mask) #調(diào)用監(jiān)聽函數(shù), key的fileobj屬性獲取被監(jiān)聽的socket對象
#client
import selectors, socket, threading
sel = selectors.DefaultSelector() # 創(chuàng)建默認(rèn)的selectors對象
def read(conn, mask): # 負(fù)責(zé)監(jiān)聽“有數(shù)據(jù)可讀”事件的函數(shù)data = conn.recv(1024) # Should be readyif data:print(data.decode('utf-8'))else:print('closing', conn)sel.unregister(conn)conn.close()
s = socket.socket() # 創(chuàng)建socket對象
s.connect(('192.168.101.9', 30000))# 連接遠(yuǎn)程主機(jī)
s.setblocking(False) # 設(shè)置該socket是非阻塞的
sel.register(s, selectors.EVENT_READ, read)#使用sel為s的EVENT_READ事件注冊read監(jiān)聽函數(shù)
def keyboard_input(s): # 定義不斷讀取用戶鍵盤輸入的函數(shù)while True:line = input('')if line == 'exit':breaks.send(line.encode('utf-8'))# 將用戶的鍵盤輸入內(nèi)容寫入socket
threading.Thread(target=keyboard_input, args=(s, )).start()# 采用線程不斷讀取用戶的鍵盤輸入
while True:events = sel.select()# 獲取事件for key, mask in events:callback = key.data# key的data屬性獲取為該事件注冊的監(jiān)聽函數(shù)callback(key.fileobj, mask)# 調(diào)用監(jiān)聽函數(shù), key的fileobj屬性獲取被監(jiān)聽的socket對象#SMTP發(fā)送
import smtplib
import email
from email.message import EmailMessage
#一、設(shè)置變量
smtp_server='smtp.qq.com'#定義SMTP服務(wù)器地址:
from_addr='1064789374@qq.com'#定義發(fā)件人地址
password='lllchhbtzygrbfbb'#定義登錄郵箱的密碼,但這里是授權(quán)碼
to_addr='15521108978@163.com'#定義收件人地址
#二、連接登陸
#conn=smtplib.SMTP(smtp_server, 25)#創(chuàng)建SMTP連接普通版
conn=smtplib.SMTP_SSL(smtp_server,465)#創(chuàng)建SMTP連接SSL版
conn.set_debuglevel(1)#顯示調(diào)試過程
conn.login(from_addr, password)#登陸帳號
#三、創(chuàng)建郵件
msg = EmailMessage()#創(chuàng)建郵件對象
pic_id=email.utils.make_msgid()
with open('F:\ProjectPython\hello_test2\images\z.png','rb') as f:#正文中圖片msg.add_attachment(f.read(),maintype='image',subtype='png',filename='z.png', cid=pic_id)
with open('F:\ProjectPython\hello_test2\images\z.png','rb') as f:#附件msg.add_attachment(f.read(),maintype='application',subtype='png',filename='z.png',)
msg.set_content('老婆我愛你!'+'<img src="cid:'+pic_id[1:-1]+'">','html','utf-8')#設(shè)置郵件內(nèi)容,指定郵件內(nèi)容為HTML
msg['subject']='情書'
msg['from']='老公<%s>'%from_addr
msg['to']='老婆<%s>'%to_addr
#四、發(fā)送郵件
conn.sendmail(from_addr, [to_addr], msg.as_string())#發(fā)送郵件
conn.quit()#退出連接#POP3接收
import poplib, os.path, mimetypes
from email.policy import default
#一、輸入郵件地址, 口令和POP3服務(wù)器地址:
email = '1064789374@qq.com'
password = 'lllchhbtzygrbfbb'
pop3_server = 'pop.qq.com'
#二、連接到POP 3服務(wù)器:
#conn = poplib.POP3(pop3_server, 110)
conn = poplib.POP3_SSL(pop3_server, 995)
conn.set_debuglevel(0)# 可以打開或關(guān)閉調(diào)試信息
#print(conn.getwelcome().decode('utf-8'))# 可選:打印POP 3服務(wù)器的歡迎文字:
conn.user(email)#發(fā)送POP 3的user命令輸入用戶名、密碼信息
conn.pass_(password)#發(fā)送POP 3的pass命令獲取郵件統(tǒng)計(jì)信息,相當(dāng)于發(fā)送POP 3的stat命令
message_num, total_size = conn.stat()
print('郵件數(shù): %s. 總大小: %s' % (message_num, total_size))
resp, mails, octets = conn.list()# 發(fā)送POP 3的list命令獲取服務(wù)器上的郵件列表
#print(resp, mails)# resp保存服務(wù)器的響應(yīng)碼,mails列表保存每封郵件的編號、大小
resp,data,octets=conn.retr(len(mails))#發(fā)送POP3的retr命令獲取指定郵件內(nèi)容(傳入總長度是獲取最后一封郵件),resp響應(yīng)碼data郵件內(nèi)容
# data保存該郵件的內(nèi)容
msg_data = b'\r\n'.join(data)# 將data的所有數(shù)據(jù)(原本是一個(gè)字節(jié)列表)拼接在一起
msg=BytesParser(policy=default).parsebytes(msg_data)# 將字符串內(nèi)容解析成郵件類對象,此處一定要指定policy=default
print('發(fā)件人:' + msg['from'])
print('收件人:' + msg['to'])
print('主題:' + msg['subject'])
print('第一個(gè)收件人名字:' + msg['to'].addresses[0].username)
print('第一個(gè)發(fā)件人名字:' + msg['from'].addresses[0].username)
for part in msg.walk():#分開正文與附件,其中正文counter = 1if part.get_content_maintype()=='multipart':continue#multipart是容器(用于包含正文附件)elif part.get_content_maintype()=='text':print(part.get_content())#text是郵件正文部分else : # 處理附件filename = part.get_filename() # 獲取附件的文件名if not filename: # 如果沒有文件名,程序要負(fù)責(zé)為附件生成文件名ext = mimetypes.guess_extension(part.get_content_type())# 根據(jù)附件的contnet_type來推測它的后綴名if not ext:ext = '.bin' # 如果推測不出后綴名,使用.bin作為后綴名filename = 'part-%03d%s' % (counter, ext) # 程序?yàn)楦郊砩晌募鹀ounter += 1with open(os.path.join('.', filename), 'wb') as fp: # 將附件寫入的本地文件fp.write(part.get_payload(decode=True))
conn.quit() # 退出服務(wù)器,相當(dāng)于發(fā)送POP 3的quit命令
#第十六章:文檔測試 #doctest:自動執(zhí)行注釋里的樣例并生成錯(cuò)誤報(bào)告 def square (x):'''一個(gè)用于計(jì)算平方的函數(shù)例如>>> square(2)4>>> square(3)9>>> square(-3)9>>> square(0)0'''return x * 2 # ①、故意寫錯(cuò)的return x ** 2 class User:'''定義一個(gè)代表用戶的類,該類包含如下兩個(gè)屬性:name - 代表用戶的名字age - 代表用戶的年齡例如>>> u = User('fkjava', 9)>>> u.name'fkjava'>>> u.age9>>> u.say('i love python')'fkjava說: i love python''''def __init__(self, name, age):self.name = nameself.name = 'fkit' # ②、故意寫錯(cuò)的self.age = agedef say(self, content):return self.name + '說: ' + content if __name__=='__main__':import doctestdoctest.testmod()#單元測試邏輯覆蓋 def test (a, b, m):if a > 10 and b == 0:m = a + bif a == 20 or m > 15:m += 1 ''' 一、語句覆蓋:每條語句都至少執(zhí)行一次 a=20,b=0,m=3 兩真 二、判定(邊)覆蓋/分支覆蓋:每個(gè)判斷分支取真取假各至少執(zhí)行一次(a>10與b==0是同一分支) a=20,b=0,m=3 兩真 a=10,b=0,m=3 兩假 三、條件覆蓋:每個(gè)判斷中每個(gè)條件的可能取值都至少滿足一次(a>10與b==0是兩個(gè)條件) a=20,b=1,m=10 先假再真 a=9,b=0,m=20 先假再真 四、判定-條件覆蓋:每個(gè)條件所有可能的組合至少出現(xiàn)一次 a=20,b=0,m=3 兩真 a=20,b=1,m=10 先假再真 a=10,b=0,m=20 兩假 a=1,b=2,m=3 兩假 五、路徑覆蓋:覆蓋所有路徑 a=20,b=0,m=3 兩真 a=5,b=0,m=2 兩假 a=20,b=1,m=10 先假再真 a=20,b=0,m=7 先真再假 '''#測試用類例 #fk_math.py def one_equation(a , b):'''求一元一次方程a * x + b = 0的解參數(shù)a - 方程中變量的系數(shù)參數(shù)b - 方程中的常量返回 方程的解'''# 如果a = 0,則方程無法求解if a == 0:raise ValueError("參數(shù)錯(cuò)誤")# 返回方程的解else: # return -b / a # ①return b / a def two_equation(a , b , c):'''求一元二次方程a * x * x + b * x + c = 0的解參數(shù)a - 方程中變量二次冪的系數(shù)參數(shù)b - 方程中變量的系數(shù)參數(shù)c - 方程中的常量返回 方程的根'''if a == 0:raise ValueError("參數(shù)錯(cuò)誤")# 如果a == 0,變成一元一次方程elif b * b - 4 * a * c < 0:raise ValueError("方程在有理數(shù)范圍內(nèi)無解")elif b * b - 4 * a * c == 0:return -b / (2 * a)# 方程有唯一的解else:r1 = (-b + (b * b - 4 * a * c) ** 0.5) / 2 / ar2 = (-b - (b * b - 4 * a * c) ** 0.5) / 2 / areturn r1, r2# 方程的兩個(gè)解 #test_fk_math.py import unittest from fk_math import * class TestFkMath(unittest.TestCase):def test_one_equation(self):# 測試一元一次方程的求解self.assertEqual(one_equation(5 , 9) , -1.8)# 斷言該方程求解應(yīng)該為-1.8self.assertTrue(one_equation(4 , 10) == -2.5 , .00001)# 斷言該方程求解應(yīng)該為-2.5self.assertTrue(one_equation(4 , -27) == 27 / 4)# 斷言該方程求解應(yīng)該為27/4with self.assertRaises(ValueError):one_equation(0 , 9)# 斷言當(dāng)a == 0時(shí)的情況,斷言引發(fā)ValueErrordef test_two_equation(self):# 測試一元二次方程的求解self.assertCountEqual(two_equation(1 , -3 , 2), (1.0, 2.0), '求解出錯(cuò)')self.assertCountEqual(two_equation(2 , -7 , 6), (1.5, 2.0), '求解出錯(cuò)')self.assertEqual(two_equation(1 , -4 , 4), 2.0, '求解出錯(cuò)')# 斷言只有一個(gè)解的情形with self.assertRaises(ValueError):two_equation(0, 9, 3)# 斷言當(dāng)a == 0時(shí)的情況,斷言引發(fā)ValueErrorwith self.assertRaises(ValueError):two_equation(4, 2, 3)# 斷言引發(fā)ValueError if __name__ == '__main__':unittest.main()#測試包與運(yùn)行器(就是把前面的測試用例組合起來) #hello.py def say_hello():return "Hello World." def add(nA, nB):return nA + nB #test_hello.py import unittest from hello import * class TestHello(unittest.TestCase):def test_say_hello(self):self.assertEqual(say_hello() , "Hello World.")def test_add(self):self.assertEqual(add(3, 4) , 7)self.assertEqual(add(0, 4) , 4)self.assertEqual(add(-3, 0) , -3) #suite_test.py import unittest from test_fk_math import TestFkMath from test_hello import TestHello test_cases = (TestHello, TestFkMath) def whole_suite():loader = unittest.TestLoader()# 創(chuàng)建測試加載器suite = unittest.TestSuite()# 創(chuàng)建測試包for test_class in test_cases:# 遍歷所有測試類tests = loader.loadTestsFromTestCase(test_class)# 從測試類中加載測試用例suite.addTests(tests)# 將測試用例添加到測試包中return suite if __name__ == '__main__':with open('fk_test_report.txt', 'a') as f:runner = unittest.TextTestRunner(verbosity=2, stream=f)#創(chuàng)建測試運(yùn)行器(TestRunner),測試報(bào)告輸出到文件中runner.run(whole_suite())#測試 #第十七章:pyinstaller #Python_test2.py文件 def say_hello(name):return name + ",您好!"#Python_test3.py文件 from Python_test2 import * def main():print('程序開始執(zhí)行')print(say_hello('孫悟空')) # 增加調(diào)用main()函數(shù) if __name__ == '__main__':main()#命令行的代碼 #pyinstaller -F F:\ProjectPython\hello_test2\Python_test3.py #-F表示生成一個(gè)大EXE文件,-D表示生成一個(gè)目錄(動態(tài)重定位),加-w取消命令行 #-n NAME或-name NAME可以指定項(xiàng)目名字,如果省略則第一個(gè)腳本的主文件名將作為spec名字(其實(shí)就是main.py,你在開發(fā)的時(shí)候把這個(gè)主程序入口的py文件命名好就行了,例如tank_game.py則最后就會生成tank_game.exe) #現(xiàn)在還未知道如何改圖標(biāo) #第十八章:pygame import pygame def main():pygame.init() #初始化screen=pygame.display.set_mode((1024,640)) #開窗口pygame.display.set_caption("tank game") #定標(biāo)題background=pygame.Surface(screen.get_size())#獲大小background=background.convert() #屏幕轉(zhuǎn)像素background.fill((100,100,100)) #白色填充clock=pygame.time.Clock() #開定時(shí)器running=True #運(yùn)行標(biāo)志while running: #主程序大循環(huán)clock.tick(30) #最大每秒30幀for event in pygame.event.get(): #檢測退出信息if event.type==pygame.QUIT: #如果有的話running=False #更改標(biāo)志位screen.blit(background,(0,0)) #位塊傳送把背景回到左上角#鼠標(biāo)事件buttons=pygame.mouse.get_pressed() #獲鼠標(biāo)按下事件if buttons[0]:print(pygame.mouse.get_pos()) #按左鍵輸出坐標(biāo)#鍵盤事件keys=pygame.key.get_pressed() #獲鍵盤按下事件if keys[pygame.K_SPACE]:print('space') #按下空格輸出space#繪圖:畫矩形(在screen上畫,[r,g,b],[左上角x,y,長,寬],線寬),線寬取0是填充pygame.draw.rect(screen,[255,0,0],[600,600,10,10],0)#貼圖maps = pygame.image.load('GJL.png') #獲取圖片screen.blit(maps,(0,0)) #貼到screen的左上角pygame.display.update() #更新顯示pygame.quit() #退出游戲 main()''' KeyASCII ASCII 描述 K_BACKSPACE \b 退格鍵(Backspace) K_TAB \t 制表鍵(Tab) K_CLEAR 清楚鍵(Clear) K_RETURN \r 回車鍵(Enter) K_PAUSE 暫停鍵(Pause) K_ESCAPE ^[ 退出鍵(Escape) K_SPACE 空格鍵(Space) K_EXCLAIM ! 感嘆號(exclaim) K_QUOTEDBL " 雙引號(quotedbl) K_HASH # 井號(hash) K_DOLLAR $ 美元符號(dollar) K_AMPERSAND & and 符號(ampersand) K_QUOTE ' 單引號(quote) K_LEFTPAREN ( 左小括號(left parenthesis) K_RIGHTPAREN ) 右小括號(right parenthesis) K_ASTERISK * 星號(asterisk) K_PLUS + 加號(plus sign) K_COMMA , 逗號(comma) K_MINUS - 減號(minus sign) K_PERIOD . 句號(period) K_SLASH / 正斜杠(forward slash) K_0 0 0 K_1 1 1 K_2 2 2 K_3 3 3 K_4 4 4 K_5 5 5 K_6 6 6 K_7 7 7 K_8 8 8 K_9 9 9 K_COLON : 冒號(colon) K_SEMICOLON ; 分號(semicolon) K_LESS < 小于號(less-than sign) K_EQUALS = 等于號(equals sign) K_GREATER > 大于號(greater-than sign) K_QUESTION ? 問號(question mark) K_AT @ at 符號(at) K_LEFTBRACKET [ 左中括號(left bracket) K_BACKSLASH \ 反斜杠(backslash) K_RIGHTBRACKET ] 右中括號(right bracket) K_CARET ^ 脫字符(caret) K_UNDERSCORE _ 下劃線(underscore) K_BACKQUOTE ` 重音符(grave) K_a a a K_b b b K_c c c K_d d d K_e e e K_f f f K_g g g K_h h h K_i i i K_j j j K_k k k K_l l l K_m m m K_n n n K_o o o K_p p p K_q q q K_r r r K_s s s K_t t t K_u u u K_v v v K_w w w K_x x x K_y y y K_z z z K_DELETE 刪除鍵(delete) K_KP0 0(小鍵盤) K_KP1 1(小鍵盤) K_KP2 2(小鍵盤) K_KP3 3(小鍵盤) K_KP4 4(小鍵盤) K_KP5 5(小鍵盤) K_KP6 6(小鍵盤) K_KP7 7(小鍵盤) K_KP8 8(小鍵盤) K_KP9 9(小鍵盤) K_KP_PERIOD . 句號(小鍵盤) K_KP_DIVIDE / 除號(小鍵盤) K_KP_MULTIPLY * 乘號(小鍵盤) K_KP_MINUS - 減號(小鍵盤) K_KP_PLUS + 加號(小鍵盤) K_KP_ENTER \r 回車鍵(小鍵盤) K_KP_EQUALS = 等于號(小鍵盤) K_UP 向上箭頭(up arrow) K_DOWN 向下箭頭(down arrow) K_RIGHT 向右箭頭(right arrow) K_LEFT 向左箭頭(left arrow) K_INSERT 插入符(insert) K_HOME Home 鍵(home) K_END End 鍵(end) K_PAGEUP 上一頁(page up) K_PAGEDOWN 下一頁(page down) K_F1 F1 K_F2 F2 K_F3 F3 K_F4 F4 K_F5 F5 K_F6 F6 K_F7 F7 K_F8 F8 K_F9 F9 K_F10 F10 K_F11 F11 K_F12 F12 K_F13 F13 K_F14 F14 K_F15 F15 K_NUMLOCK 數(shù)字鍵盤鎖定鍵(numlock) K_CAPSLOCK 大寫字母鎖定鍵(capslock) K_SCROLLOCK 滾動鎖定鍵(scrollock) K_RSHIFT 右邊的 shift 鍵(right shift) K_LSHIFT 左邊的 shift 鍵(left shift) K_RCTRL 右邊的 ctrl 鍵(right ctrl) K_LCTRL 左邊的 ctrl 鍵(left ctrl) K_RALT 右邊的 alt 鍵(right alt) K_LALT 左邊的 alt 鍵(left alt) K_RMETA 右邊的元鍵(right meta) K_LMETA 左邊的元鍵(left meta) K_LSUPER 左邊的 Window 鍵(left windows key) K_RSUPER 右邊的 Window 鍵(right windows key) K_MODE 模式轉(zhuǎn)換鍵(mode shift) K_HELP 幫助鍵(help) K_PRINT 打印屏幕鍵(print screen) K_SYSREQ 魔術(shù)鍵(sysrq) K_BREAK 中斷鍵(break) K_MENU 菜單鍵(menu) K_POWER 電源鍵(power) K_EURO 歐元符號(euro) ''' 第十九章:matplotlib #入門 import matplotlib.pyplot as plt import numpy as np plt.figure() plt.subplot(2,1,1)#將整個(gè)figure分成兩行兩列,并將下面圖形放在第4個(gè)網(wǎng)格 x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] ln1,=plt.plot(x_data,y_data,color='red',linewidth=2.0,linestyle='--',label='cj')#折線顏色、線寬和樣式 ln2,=plt.plot(x_data,y_data2,color='blue',linewidth=3.0,linestyle='-.',label='gjl')#-實(shí)線--虛線:點(diǎn)線-.點(diǎn)虛線 plt.legend(loc='lower right')#調(diào)用legend函數(shù)設(shè)置圖例,location默認(rèn)是'best'自動選擇最佳位置 plt.xlabel('year') plt.ylabel('salary') plt.title('gogogo') #plt.yticks([50000,70000,100000],[r'A',r'B',r'C'])#這行出現(xiàn)就會代替Y坐標(biāo)值 #plt.show()# 調(diào)用show()函數(shù)顯示圖形 ax = plt.gca()#返回的是axis坐標(biāo)軸 ax.spines['bottom'].set_position(('data',70000))#設(shè)置坐標(biāo)軸的bottom處的位置是data=70000處 #ax.yaxis.set_ticks_position('left')#設(shè)置坐標(biāo)軸的Y軸的位置在left處,可以無視,默認(rèn)就是這樣 #ax.xaxis.set_ticks_position('bottom')#設(shè)置坐標(biāo)軸的X軸的的位置在bottom處,可以無視,默認(rèn)就是這樣 #ax.spines['right'].set_color('red')#設(shè)置右邊坐標(biāo)軸線的顏色(設(shè)置為none表示不顯示),可以無視,沒啥用 #ax.spines['top'].set_color('blue')#設(shè)置頂部坐標(biāo)軸線的顏色(設(shè)置為none表示不顯示),可以無視,沒啥用 plt.subplot(2,1,2)#將整個(gè)figure分成兩行兩列,第三個(gè)參數(shù)表示下面的圖形放在第1個(gè)網(wǎng)格 x_data=np.linspace(-np.pi,np.pi,64,endpoint=True)#利用np.pi線性均分成64個(gè)點(diǎn) plt.plot(x_data, np.sin(x_data))#開始繪制正弦曲線,注意此時(shí)的plt是畫在212位置的 plt.gca().spines['right'].set_color('none') plt.gca().spines['top'].set_color('none') plt.gca().spines['bottom'].set_position(('data', 0)) plt.gca().spines['left'].set_position(('data', 0)) plt.title('sin') plt.show()#子圖 import matplotlib.pyplot as plt import numpy as np import matplotlib.gridspec as gridspec plt.figure() x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)#取生成x點(diǎn) gs = gridspec.GridSpec(2, 3)# 將繪圖區(qū)域分成2行3列 ax1 = plt.subplot(gs[0, :])# 指定ax1占用第零行 ax2 = plt.subplot(gs[1, 0])# 指定ax1占用第一行的第零格 ax3 = plt.subplot(gs[1, 1:3])# 指定ax1占用一行的第二、三格 ax1.plot(x_data, np.sin(x_data))# 繪制正弦曲線 ax1.spines['right'].set_color('none') ax1.spines['top'].set_color('none') ax1.spines['bottom'].set_position(('data', 0)) ax1.spines['left'].set_position(('data', 0)) ax1.set_title('sin') ax2.plot(x_data, np.cos(x_data))# 繪制余弦曲線 ax2.spines['right'].set_color('none') ax2.spines['top'].set_color('none') ax2.spines['bottom'].set_position(('data', 0)) ax2.spines['left'].set_position(('data', 0)) ax2.set_title('cos') ax3.plot(x_data, np.tan(x_data))# 繪制正切曲線 ax3.spines['right'].set_color('none') ax3.spines['top'].set_color('none') ax3.spines['bottom'].set_position(('data', 0)) ax3.spines['left'].set_position(('data', 0)) ax3.set_title('tan') plt.show()#餅圖 import matplotlib.pyplot as plt data=[0.16881, 0.14966, 0.07471, 0.06992,0.04762, 0.03541, 0.02925, 0.02411, 0.02316, 0.01409, 0.36326] labels=['Java','C','C++','Python','Visual Basic .NET','C#','PHP','JavaScript','SQL','Assembly langugage','other'] explode = [0, 0, 0, 0.3, 0, 0, 0, 0, 0, 0, 0]# 將第4個(gè)語言(Python)分離出來 colors=['red', 'pink', 'magenta','purple','orange'] # 使用自定義顏色 plt.axes(aspect='equal')#正圓 plt.xlim(0,8)#邊框大小 plt.ylim(0,8)#邊框大小 plt.pie(x = data, # 繪圖數(shù)據(jù)labels=labels, # 添加編程語言標(biāo)簽explode=explode, # 突出顯示Pythoncolors=colors, # 設(shè)置餅圖的自定義填充色autopct='%.3f%%', # 設(shè)置百分比的格式,此處保留3位小數(shù)pctdistance=0.8, # 設(shè)置百分比標(biāo)簽與圓心的距離labeldistance = 1.15, # 設(shè)置標(biāo)簽與圓心的距離startangle = 180, # 設(shè)置餅圖的初始角度center = (4, 4), # 設(shè)置餅圖的圓心(相當(dāng)于X軸和Y軸的范圍)radius = 3.8, # 設(shè)置餅圖的半徑(相當(dāng)于X軸和Y軸的范圍)counterclock = False, # 是否逆時(shí)針,這里設(shè)置為順時(shí)針方向wedgeprops = {'linewidth': 1, 'edgecolor':'green'},# 設(shè)置餅圖內(nèi)外邊界的屬性值textprops = {'fontsize':12, 'color':'black'}, # 設(shè)置文本標(biāo)簽的屬性值frame = 1) # 是否顯示餅圖的圓圈,此處設(shè)為顯示 plt.xticks(()) plt.yticks(()) plt.title('2018-08 languagu rank') plt.show()#豎柱狀圖 import matplotlib.pyplot as plt import numpy as np x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] bar_width=0.3 #range(len(x_data)就是0、1、2控制中心坐標(biāo)故np.arange(len(x_data))是左柱中心坐標(biāo),加+bar_width就是右柱中心坐標(biāo) plt.bar(x=range(len(x_data)),height=y_data,label='CJ',color='steelblue', alpha=0.8, width=bar_width) plt.bar(x=np.arange(len(x_data))+bar_width+0.05, height=y_data2,label='GJL', color='indianred', alpha=0.8, width=bar_width) for x,y in enumerate(y_data):plt.text(x,y,'%s'%y,ha='center',va='bottom')#x,y是坐標(biāo),'%s'%y是內(nèi)容 for x,y in enumerate(y_data2):plt.text(x+bar_width,y,'%s'%y,ha='center',va='top')#ha水平對齊, va垂直對齊 plt.xticks(np.arange(len(x_data))+bar_width/2, x_data)# 為X軸設(shè)置刻度值 plt.title("CJ&GJL")#設(shè)置標(biāo)題 plt.xlabel("year")#X標(biāo)簽 plt.ylabel("salary")#Y標(biāo)答 plt.legend()#圖例 plt.show() #橫柱狀圖 import matplotlib.pyplot as plt import numpy as np x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] bar_width=0.3 plt.barh(y=range(len(x_data)), width=y_data, label='CJ',color='steelblue', alpha=0.8, height=bar_width) plt.barh(y=np.arange(len(x_data))+bar_width, width=y_data2,label='GJL', color='indianred', alpha=0.8, height=bar_width) for y, x in enumerate(y_data):plt.text(x+5000,y-bar_width/2,'%s'%x,ha='center',va='bottom') for y, x in enumerate(y_data2):plt.text(x+5000,y+bar_width/2,'%s'%x,ha='center',va='bottom') plt.yticks(np.arange(len(x_data))+bar_width/2, x_data)# 為Y軸設(shè)置刻度值 plt.title("CJ&GJL")#設(shè)置標(biāo)題 plt.xlabel("year")#X標(biāo)簽 plt.ylabel("salary")#Y標(biāo)答 plt.legend()#圖例 plt.show()#散點(diǎn)圖 import matplotlib.pyplot as plt import numpy as np plt.figure() x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)# 定義從-pi到pi之間的數(shù)據(jù),平均取64個(gè)數(shù)據(jù)點(diǎn) plt.scatter(x_data, #x值np.sin(x_data), #y值c='purple', #設(shè)置點(diǎn)的顏色s=50, #設(shè)置點(diǎn)半徑alpha = 0.5, #設(shè)置透明度marker='p', #設(shè)置使用五邊形標(biāo)記linewidths=1, #設(shè)置邊框的線寬edgecolors=['green', 'yellow']) # 設(shè)置邊框的顏色 plt.scatter(x_data[0], np.sin(x_data)[0], c='red',s=150, alpha = 1) plt.scatter(x_data[63], np.sin(x_data)[63], c='black',s=150,alpha = 1) plt.gca().spines['right'].set_color('none') plt.gca().spines['top'].set_color('none') plt.gca().spines['bottom'].set_position(('data', 0)) plt.gca().spines['left'].set_position(('data', 0)) plt.title('sin') plt.show()#等高線圖 import matplotlib.pyplot as plt import numpy as np delta = 0.025 x=np.arange(-3.0,3.0,delta)#生成代表X軸數(shù)據(jù)的列表 y=np.arange(-2.0,2.0,delta)#生成代表Y軸數(shù)據(jù)的列表 X,Y=np.meshgrid(x, y)#對x、y數(shù)據(jù)執(zhí)行網(wǎng)格化 Z1=np.exp(-X**2-Y**2) Z2=np.exp(-(X-1)**2-(Y-1)**2) Z=(Z1-Z2)*2# 計(jì)算Z軸數(shù)據(jù)(高度數(shù)據(jù)) plt.contourf(x,y,Z,16,alpha=0.75,cmap='rainbow')#使用顏色映射來區(qū)分16種不同高度的區(qū)域 C=plt.contour(x,y,Z,16,#繪制等高線colors='black',#指定等高線的顏色linewidth=0.5)#指定等高線的線寬 plt.clabel(C, inline = True, fontsize = 10)#繪制等高線數(shù)據(jù) plt.xticks(())#去除坐標(biāo)軸 plt.yticks(())#去除坐標(biāo)軸 plt.title("contour") plt.xlabel("x") plt.ylabel("y") plt.show()#3D圖形 import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(figsize=(12, 8)) ax = Axes3D(fig) delta = 0.125 x = np.arange(-3.0, 3.0, delta)# 生成代表X軸數(shù)據(jù)的列表 y = np.arange(-2.0, 2.0, delta)# 生成代表Y軸數(shù)據(jù)的列表 X, Y = np.meshgrid(x, y)# 對x、y數(shù)據(jù)執(zhí)行網(wǎng)格化 Z1 = np.exp(-X**2 - Y**2) Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2) Z = (Z1 - Z2) * 2# 計(jì)算Z軸數(shù)據(jù)(高度數(shù)據(jù)) ax.plot_surface(X, Y, Z, # 繪制3D圖形rstride=1, # rstride(row)指定行的跨度cstride=1, # cstride(column)指定列的跨度cmap=plt.get_cmap('rainbow')) # 設(shè)置顏色映射 ax.set_zlim(-2, 2)# 設(shè)置Z軸范圍 plt.title("3D")# 設(shè)置標(biāo)題 plt.show()#pygal:實(shí)在太簡單了,缺點(diǎn)是必須用瀏覽器看 import pygal#例一柱圖 y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] bar = pygal.Bar()# 創(chuàng)建pygal.Bar對象(柱狀圖) bar.add('Java', y_data)# 添加兩組代表?xiàng)l柱的數(shù)據(jù) bar.add('Android', y_data2) bar.render_to_file('fk_books.svg')# 添加兩組代表?xiàng)l柱的數(shù)據(jù)#例二柱圖加強(qiáng)版 x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] bar.x_labels = x_data# 設(shè)置X軸的刻度值 bar.title = '銷量' bar.x_title = '年份' bar.y_title = '銷量' bar.x_label_rotation = 45# 設(shè)置X軸的刻度值旋轉(zhuǎn)45度 bar.legend_at_bottom = True# 設(shè)置將圖例放在底部 bar.margin = 35# 設(shè)置數(shù)據(jù)圖四周的頁邊距,也可通過margin_bottom、margin_left、margin_right、margin_top只設(shè)置單獨(dú)一邊的頁邊距 bar.show_y_guides=False# 隱藏Y軸上的網(wǎng)格線 bar.show_x_guides=True# 顯示X軸上的網(wǎng)格線 bar.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#例三折線圖 line = pygal.Line()# 創(chuàng)建pygal.Line對象(折線圖) line.add('Java', y_data)# 添加兩組代表折線的數(shù)據(jù) line.add('Android', y_data2) line.x_labels = x_data# 設(shè)置X軸的刻度值 line.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置Y軸的刻度值 line.title = '銷量' line.x_title = '年份' line.y_title = '銷量' line.legend_at_bottom = True# 設(shè)置將圖例放在底部 line.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#水平柱狀圖 horizontal_bar = pygal.HorizontalBar()# 創(chuàng)建pygal.HorizontalBar對象(水平柱狀圖) horizontal_bar.add('Java', y_data)# 添加兩組數(shù)據(jù) horizontal_bar.add('Android', y_data2) horizontal_bar.x_labels = x_data# 設(shè)置Y軸的刻度值(注意xy這里掉亂說的,有點(diǎn)迷糊) horizontal_bar.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置X軸的刻度值 horizontal_bar.title = '銷量' horizontal_bar.x_title = '銷量' horizontal_bar.y_title = '年份' horizontal_bar.legend_at_bottom = True# 設(shè)置將圖例放在底部 horizontal_bar.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#水平折線圖 horizontal_line = pygal.HorizontalLine()# 創(chuàng)建pygal.HorizontalLine對象(水平折線圖) horizontal_line.add('Java', y_data)# 添加兩組代表折線的數(shù)據(jù) horizontal_line.add('Android', y_data2) horizontal_line.x_labels = x_data# 設(shè)置Y軸(確實(shí)如此)的刻度值 horizontal_line.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置X軸(確實(shí)如此)的刻度值 horizontal_line.title = '銷量' horizontal_line.x_title = '銷量' horizontal_line.y_title = '年份' horizontal_line.legend_at_bottom = True# 設(shè)置將圖例放在底部 horizontal_line.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#疊加柱狀圖 stacked_bar = pygal.StackedBar() stacked_bar.add('Java', y_data)# 添加兩組數(shù)據(jù) stacked_bar.add('Android', y_data2) stacked_bar.x_labels = x_data# 設(shè)置X軸的刻度值 stacked_bar.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置Y軸的刻度值 stacked_bar.title = '銷量' stacked_bar.x_title = '銷量' stacked_bar.y_title = '年份' stacked_bar.legend_at_bottom = True# 設(shè)置將圖例放在底部 stacked_bar.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#疊加折線圖 stacked_line = pygal.StackedLine() stacked_line.add('Java', y_data)# 添加兩組數(shù)據(jù) stacked_line.add('Android', y_data2) stacked_line.x_labels = x_data# 設(shè)置X軸的刻度值 stacked_line.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置Y軸的刻度值 stacked_line.title = '銷量' stacked_line.x_title = '銷量' stacked_line.y_title = '年份' stacked_line.legend_at_bottom = True# 設(shè)置將圖例放在底部 stacked_line.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#點(diǎn)圖 dot = pygal.Dot() dot.dots_size = 5 dot.add('Java', y_data)# 添加兩組數(shù)據(jù) dot.add('Android', y_data2) dot.x_labels = x_data# 設(shè)置X軸的刻度值 dot.y_labels = ['Java', 'Android']# 重新設(shè)置Y軸的刻度值 dot.y_label_rotation = 45# 設(shè)置Y軸刻度值的旋轉(zhuǎn)角度 dot.title = '銷量' dot.x_title = '年份' dot.legend_at_bottom = True# 設(shè)置將圖例放在底部 dot.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#餅圖 data=[0.16881,0.14966,0.07471,0.06992,0.04762,0.03541,0.02925,0.02411,0.02316,0.01409,0.36326] labels=['Java','C','C++','Python','Visual Basic .NET','C#','PHP','JavaScript','SQL','Assembly langugage','其他']# 準(zhǔn)備標(biāo)簽 pie = pygal.Pie()# 創(chuàng)建pygal.Pie對象(餅圖) for i, per in enumerate(data): pie.add(labels[i], per)# 采用循環(huán)為餅圖添加數(shù)據(jù) pie.title = '2018年8月編程語言' pie.legend_at_bottom = True# 設(shè)置將圖例放在底部 pie.inner_radius = 0.4# 設(shè)置內(nèi)圈的半徑長度 pie.half_pie = True# 創(chuàng)建半圓數(shù)據(jù)圖 pie.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#儀表圖 gauge = pygal.Gauge()# 創(chuàng)建pygal.Gauge對象(儀表圖) gauge.range = [0, 1] for i, per in enumerate(data):gauge.add(labels[i], per)# 采用循環(huán)為儀表圖添加數(shù)據(jù) gauge.title = '2018年8月編程語言' gauge.legend_at_bottom = True# 設(shè)置將圖例放在底部 gauge.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#雷達(dá)圖 data = [[5, 4.0, 5, 5, 5],# 準(zhǔn)備數(shù)據(jù)[4.8, 2.8, 4.8, 4.8, 4.9],[4.5, 2.9, 4.6, 4.0, 4.9],[4.0, 4.8, 4.9, 4.0, 5],[3.0, 4.2, 2.3, 3.5, 2],[4.8, 4.3, 3.9, 3.0, 4.5]] labels = ['Java', 'C', 'C++', 'Python','C#', 'PHP']# 準(zhǔn)備標(biāo)簽 rader = pygal.Radar()# 創(chuàng)建pygal.Radar對象(雷達(dá)圖) for i, per in enumerate(labels):rader.add(labels[i], data[i])# 采用循環(huán)為雷達(dá)圖添加數(shù)據(jù) rader.x_labels = ['平臺健壯性', '語法易用性', '社區(qū)活躍度','市場份額', '未來趨勢'] rader.title = '編程語言對比圖' rader.dots_size = 8# 控制各數(shù)據(jù)點(diǎn)的大小 rader.legend_at_bottom = True# 設(shè)置將圖例放在底部 rader.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#csv import csv import pygal from datetime import datetime from datetime import timedelta with open('guangzhou-2017.csv') as f:# 打開文件reader = csv.reader(f)# 創(chuàng)建cvs文件讀取器header_row = next(reader)# 讀取第一行,這行是表頭數(shù)據(jù)。print(header_row)shades, sunnys, cloudys, rainys = 0, 0, 0, 0# 準(zhǔn)備展示的數(shù)據(jù)prev_day = datetime(2016, 12, 31)for row in reader:try:cur_day = datetime.strptime(row[0], '%Y-%m-%d')# 將第一列的值格式化為日期description = row[3]except ValueError:print(cur_day, '數(shù)據(jù)出現(xiàn)錯(cuò)誤')else:diff = cur_day - prev_day# 計(jì)算前、后兩天數(shù)據(jù)的時(shí)間差if diff != timedelta(days=1):# 如果前、后兩天數(shù)據(jù)的時(shí)間差不是相差一天,說明數(shù)據(jù)有問題print('%s之前少了%d天的數(shù)據(jù)' % (cur_day, diff.days - 1))prev_day = cur_day if '陰' in description:shades += 1elif '晴' in description:sunnys += 1elif '云' in description:cloudys += 1elif '雨' in description:rainys += 1else:print(description) pie = pygal.Pie()# 創(chuàng)建pygal.Pie對象(餅圖) pie.add("陰", shades)# 為餅圖添加數(shù)據(jù) pie.add("晴", sunnys) pie.add("多云", cloudys) pie.add("雨", rainys) pie.title = '2017年廣州天氣匯總' pie.legend_at_bottom = True# 設(shè)置將圖例放在底部 pie.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#json import json with open('gdp_json.json') as f:gpd_list = json.load(f) for gpd_dict in gpd_list:# 遍歷列表的每個(gè)元素,每個(gè)元素是一個(gè)GDP數(shù)據(jù)項(xiàng)if gpd_dict['Year']==2016 and gpd_dict['Country Code']=='CHN':#中國2016年GDPprint(gpd_dict['Country Name'], gpd_dict['Value']) #第二十章:自動登陸及刷閱讀量 from selenium import webdriver from time import sleep url='http://www.51cto.com'#定義網(wǎng)址 browser=webdriver.Chrome()#打開瀏覽器并獲句柄 browser.maximize_window() #最大化窗口 browser.get(url) #打開URL browser.find_element_by_xpath('//*[@id="login_status"]/a[1]').click()#點(diǎn)擊登陸按鈕 browser.find_element_by_xpath('//*[@id="loginform-username"]').clear()#帳戶框清空 browser.find_element_by_xpath('//*[@id="loginform-username"]').send_keys('13690670863')#輸入帳號 browser.find_element_by_xpath('//*[@id="loginform-password"]').clear()#密碼框清空 browser.find_element_by_xpath('//*[@id="loginform-password"]').send_keys('abcde123456789')#輸入密碼 sleep(3)#延時(shí)三秒 browser.find_element_by_xpath('//*[@id="login-form"]/div[3]/input').click()#點(diǎn)擊確定 sleep(3)#延時(shí)三秒 browser.quit()#退出
?
?
?
?
?
?
?
?
?下面是聊天室程序
??
服務(wù)端:```pythonimport asyncore,asynchat # 導(dǎo)入兩包c(diǎn)lass ChatServer(asyncore.dispatcher): # 服務(wù)器類def __init__(self,port): # 構(gòu)造函數(shù)asyncore.dispatcher.__init__(self) # 父類初始化(不寫會默認(rèn)調(diào)用,但重寫了就要顯式用父類才調(diào)用)self.create_socket() # 創(chuàng)建socketself.set_reuse_addr() # 地址重用self.bind(('127.0.0.1',port)) # 綁定self.listen(5) # 偵聽,最大有五個(gè)連接等待被接入self.users={} # 創(chuàng)建用戶列表self.main_room=ChatRoom(self) # 主房間是聊天房間(為何放在server類這?因僅1服務(wù)器也僅1房間)def handle_accepted(self,sock,addr): # 處理用戶的接入print('socket:',sock,'addr:',addr) # 打印socket與addrChatSession(self,sock) # 創(chuàng)建一個(gè)聊天會話類,把self(下面的server)與socket傳過去class ChatSession(asynchat.async_chat): # 聊天會話類,負(fù)責(zé)與客戶端通訊def __init__(self,server,sock): # 構(gòu)造函數(shù)asynchat.async_chat.__init__(self,sock) # 父類的構(gòu)造函數(shù)就是顯式調(diào)用self.server=server # 復(fù)合類(把上面的類傳下來了)self.set_terminator(b'\n') # 數(shù)據(jù)結(jié)束標(biāo)志self.data=[] # 接受客戶端的接口數(shù)據(jù)self.name=None # 保存用戶名字self.enter(LoginRoom(self.server)) # 變登陸狀態(tài)def enter(self,room): # 從當(dāng)前房間移除自身,然后添加到指定房間try: # 嘗試cur=self.room # 取出當(dāng)前狀態(tài)except AttributeError: # 沒有的話pass # 跳過else: # 否則,就是有當(dāng)前狀態(tài)roomcur.remove(self) # 就移除self.room=room # 把新狀態(tài)更新為傳入的狀態(tài)(上面剛創(chuàng)建LoginRoom就存到這)room.add(self) # 新狀態(tài)增加我def collect_incoming_data(self, data): # 收集接口出現(xiàn)數(shù)據(jù)self.data.append(data.decode()) # 數(shù)據(jù)添加def found_terminator(self): # 找到了結(jié)束符line=''.join(self.data) # 將消息拼接成字符串self.data=[] # 把接口數(shù)據(jù)清空self.room.handle(self,line.encode()) # 處理接收的指令def handle_closed(self): # 關(guān)閉話柄asynchat.async_chat.handle_closed(self) # 父類結(jié)束方法class Room: # 狀態(tài)類def handle(self,session,line): # 處理line=line.decode() # 解碼if not line.strip(): # 空命令return # 返回parts=line.split(' ',1) # 切2份如login abc, say hello, 或無參的logout, lookcmd=parts[0] # 讀出下標(biāo)為0的字段try: # 嘗試line=parts[1].strip() # 獲取下標(biāo)為1的字段except IndexError: # 下標(biāo)錯(cuò)誤line='' # 指令為空method=getattr(self,'do_'+cmd,None) # 獲取'do_'+cmd的方法method(session,line) # 調(diào)用這個(gè)方法def __init__(self,server): # 構(gòu)造函數(shù)self.server=server # 服務(wù)器成員屬性self.sessions=[] # 會話集合def add(self,session): # 添加會話(可看到基類方法的作用是子類重寫后可調(diào)用,避免重復(fù)寫)self.sessions.append(session) # 往會話群里加會話def remove(self,session): # 移除會話(五)self.sessions.remove(session) # 從會話群里減會話(六)def broadcast(self,line): # 廣播for session in self.sessions: # 逐個(gè)會話讀出來session.push(line) # 發(fā)送內(nèi)容def do_logout(self,session,line): # 登出(一)self.remove(session) # 從當(dāng)前狀態(tài)移出會話(二)del self.server.users[session.name] # 服務(wù)器的用戶列表移除用戶名字(八)class ChatRoom(Room): # 正在聊天的客戶(成員有服務(wù)器與會話集合)def add(self,session): # 當(dāng)前狀態(tài)添加會話session.push(b'login success') # 發(fā)送login successself.broadcast((session.name+' has entered the room. \n').encode()) # 廣播self.server.users[session.name]=session # 用戶字典添加用戶名-會話鍵值對Room.add(self,session) # 狀態(tài)添加會話def remove(self,session): # 移除會話(三)Room.remove(self,session) # 狀態(tài)移除(四)self.broadcast((session.name+' has left the room.\n').encode()) # 廣播 (七)def do_say(self,session,line): # 發(fā)送信息self.broadcast((session.name+':'+line+'\n').encode()) # 廣播def do_look(self,session,line): # 查在線用戶session.push(b'Online Users:\n') # 發(fā)送Online Users:\nfor user in self.sessions: # 遍歷會話列表session.push((user.name+'\n').encode()) # 發(fā)送會話中的用戶名class LoginRoom(Room): # 正在登陸的用戶def add(self,session): # 增加Room.add(self,session) # 調(diào)用父類的添加(下面do_login末句enter會把self.room指向的對象改掉,則會話級別的LoginRoom由于不再有引用(或者說指針)指向他而被釋放,服務(wù)器級別的ChatRoom是永遠(yuǎn)只有一個(gè)且不被釋放,這就是為什么要在ChatServer中初始化ChatRoom為main_room然后在LoginRoom中傳入self.server.main_room了)session.push(b'Connect Success') # 發(fā)送信息def do_login(self,session,line): # 登陸功能name=line.strip() # 取出指令if not name: # 如果用戶名為空session.push(b'Username empty') # 發(fā)送Username emptyelif name in self.server.users: # 如果名字已在服務(wù)器用戶名列表session.push(b'Username exists') # 發(fā)送Username existselse: # 否則session.name=name # 賦值session.enter(self.server.main_room) # 進(jìn)入新的狀態(tài)(就是聊天狀態(tài))if __name__=='__main__': # 主函數(shù)print('server will run on 127.0.0.1:6666') # 提示ChatServer(6666) # 聊天服務(wù)器asyncore.loop() # 循環(huán)檢查```客戶端:```pythonimport PySimpleGUI as sgimport telnetlibdef login(conn):is_login=Falselayout=[[sg.Text('登陸Python聊天室')],[sg.Text('請輸入您的用戶名:'),sg.InputText(key='-username-'),sg.Button('進(jìn)入聊天室')]]window=sg.Window('Python聊天室',layout)while True:event,values=window.read() # 讀出窗口里面的事件if event=='進(jìn)入聊天室': # 登入事件username=values['-username-'].strip() # 取出'-username-'控件的值if username: # 用戶名非空try: # 嘗試打開連接conn.open('127.0.0.1',6666,timeout=10) # 打開except: # 否則sg.popup('連接失敗,請檢查服務(wù)器設(shè)置') # 提示break # 跳出resp=conn.read_some() # 讀回響應(yīng)if resp!=b'Connect Success': # 如果不是連接成功sg.popup('連接失敗,請檢查服務(wù)器設(shè)置') # 彈窗提示 break # 跳出conn.write(('login '+username+'\n').encode()) # 發(fā)送登陸指令resp=conn.read_some() # 讀回響應(yīng)if resp==b'Username exists': # 如果收到Username existssg.popup('用戶名已存在') # 彈窗提示失敗else: # 否則sg.popup('登陸成功') # 彈窗提示成功is_login=True # 改變標(biāo)記break # 跳出else: # 否則(用戶名為空)sg.popup('請輸入用戶名') # 彈窗提示失敗if event in (None,'Cancel'): # 退出事件break # 跳出循環(huán)window.close() # 關(guān)窗del window # 刪窗if is_login: # 判登陸標(biāo)記chat(conn,username) # 是就彈下一個(gè)窗def chat(conn,username):layout=[[sg.Text('聊天窗口('+username+')')],[sg.Multiline(disabled=True,size=(80,20),key='-chathistory-')],[sg.InputText(size=(70,5),key='-message-'),sg.Button('發(fā)送信息')],[sg.Button('查詢在線用戶'),sg.Button('退出聊天室')]]window=sg.Window('Python聊天室',layout) # 建窗while True: # 循環(huán)event,values=window.read(timeout=10) # 讀窗口信息(含接收到的信息)if values: # 值非空history_msg=values['-chathistory-'] # 讀出對話聊天記錄框字段值result=conn.read_very_eager().decode() # 讀服務(wù)器發(fā)過來的所有消息if result.strip(): # 去掉result兩邊窗白非空(那就是服務(wù)器有信息傳入)if 'Online' in result: # 出現(xiàn)Onlinesg.popup('當(dāng)前在線用戶',result) # 彈出顯示else: # 否則window['-chathistory-'].update(history_msg+'\n'+result.strip()) # 更新聊天對話窗口內(nèi)容if event in (None,'退出聊天室'): # 點(diǎn)擊x或按退出 break # 跳出循環(huán)elif event.strip()=='發(fā)送信息': # 點(diǎn)擊發(fā)送信息send(conn,'say',values['-message-']) # 發(fā)送window['-message-'].update('') # 清空編輯框elif event=='查詢在線用戶': # 點(diǎn)擊查詢在線用戶send(conn,type='look') # 發(fā)送 conn.write(b'logout\n') # 發(fā)送指令conn.close() # 關(guān)閉連接window.close() # 關(guān)窗del window # 刪窗def send(conn,type=None,msg=None): # 發(fā)if type=='say': # 說conn.write(('say '+msg +'\n').encode()) # 發(fā)elif type=='look': # 查conn.write(b'look\n') # 發(fā)if __name__=='__main__': # 主函數(shù)conn=telnetlib.Telnet() # 創(chuàng)建連接login(conn) # 調(diào)用函數(shù)``````markdownpython原生socket編程存在哪些問題一、在整個(gè)通信過程中,有很多不同的事件,這些事件需要我們自己處理,如果沒有處理則極容易產(chǎn)生異常二、必須使用多線程/多進(jìn)程方式處理多個(gè)socket客戶端的連接,而多線程在高并發(fā)場景下極容易發(fā)生C10K問題(C10指單機(jī)連接數(shù)過萬)·解決方案:IO多路復(fù)用。使用一個(gè)線程,通過記錄IO流的狀態(tài)來同時(shí)管理多個(gè)IO流,當(dāng)其中任何一個(gè)IO流的狀態(tài)發(fā)生改變,比如客戶端發(fā)送了消息過來變成為可讀狀態(tài),則再來通知該線程進(jìn)行處理。通過這種可以大大提高服務(wù)器的吞吐能力,這種方式特別適合像socket網(wǎng)絡(luò)編程這種IO密集型應(yīng)用(如果是計(jì)算密集型則的確需要多個(gè)線程)。網(wǎng)絡(luò)編程中幾個(gè)常見的易錯(cuò)概念:并發(fā):一個(gè)時(shí)間段內(nèi)有幾個(gè)程序在同一個(gè)CPU上運(yùn)行,但任意時(shí)刻只有一個(gè)程序在CPU上運(yùn)行,這種情景叫并發(fā)并行:任意時(shí)刻點(diǎn)上,有多個(gè)程序同時(shí)運(yùn)行在多個(gè)CPU上,所以最大并行數(shù)跟CPU的核心數(shù)相同同步與異步關(guān)注的是消息通信機(jī)制,關(guān)心被調(diào)用方的行為同步:代碼在調(diào)用IO操作時(shí),必須等待IO操作完成才返回的調(diào)用方式異步:代碼在調(diào)用IO操作時(shí),不必等待IO操作完成就返回的調(diào)用方式,計(jì)算完了再返回一次結(jié)果阻塞和非阻塞關(guān)注的是程序在等待調(diào)用結(jié)果時(shí)的狀態(tài),也就是調(diào)用方的狀態(tài)阻塞:調(diào)用方當(dāng)前線程被掛起,等結(jié)果回到了再激活非阻塞:調(diào)用方線程不會被掛起,而是立即返回做其他事情,過幾分鐘偶爾check一下有沒有返回結(jié)果總結(jié):同步阻塞,同步非阻塞,異步阻塞,異步非阻塞asyncore框架概念asyncore模塊是Python自帶的一個(gè)原生模塊,提供簡單的API以實(shí)現(xiàn)異步socket通信,并且為我們提供了異步socket服務(wù)器端和客戶端的基礎(chǔ)架構(gòu)在使用asyncore框架時(shí),我們需要注意兩個(gè)東西:一、全局函數(shù)loop:創(chuàng)建asyncore事件循環(huán),在事件循環(huán)中調(diào)用底層的select方法來檢測特定網(wǎng)絡(luò)信道,如果信道對應(yīng)的socket對象狀態(tài)發(fā)生改變,則自動產(chǎn)生一個(gè)高層次的事件信息,然后針對該信息調(diào)用相應(yīng)的回調(diào)方法進(jìn)行處理。二、基類dispatcher:一個(gè)底層的socket類的封裝對象,編程中繼承于dispatchero在或其子類,dispatchero在里面已經(jīng)定義好了socket通信中的各種事件,我們只需要重寫特定的事件即可在該事件發(fā)生時(shí)實(shí)現(xiàn)自動回調(diào)處理。為什么作為socket server的時(shí)候,服務(wù)器端的連接會自動斷開?因?yàn)閟ocket連接是用完即斷,所以為了保持通信服務(wù)端必須在socket連接建立好后立即創(chuàng)建一個(gè)新的dispatcher實(shí)例來保存這個(gè)socket連接對象,否則socket連接會被服務(wù)器端自動斷開補(bǔ)充handle_accept是服務(wù)端接收信息b' ' 表示這是一個(gè) bytes 對象asyncore聊天室實(shí)戰(zhàn)主要知識點(diǎn):asyncore作為服務(wù)器端的主要用法async_chat模塊的使用pySimpleGUI界面框架telnetlib作為客戶端socket模塊如何設(shè)計(jì)一個(gè)聊天室的應(yīng)用?必要條件:服務(wù)器端,多客戶端必要約束:數(shù)據(jù)傳輸協(xié)議——以換行符為消息分隔符原理:服務(wù)器監(jiān)聽消息來源,客戶端連接服務(wù)器并發(fā)送消息到服務(wù)器async_chat模塊介紹:是dispatcher這個(gè)類的抽象子類,定義了一些專門用于數(shù)據(jù)傳輸方面的方法,非常有利于實(shí)現(xiàn)數(shù)據(jù)傳輸主要方法:collect_incoming_data:接收數(shù)據(jù)found_terminator:當(dāng)輸入數(shù)據(jù)流符合由set_terminator設(shè)置的終止條件時(shí)被調(diào)用set_terminator:設(shè)置終止條件push:向數(shù)據(jù)傳輸隊(duì)列壓入要傳輸?shù)臄?shù)據(jù)···#第十六章:文檔測試 #doctest:自動執(zhí)行注釋里的樣例并生成錯(cuò)誤報(bào)告 def square (x):'''一個(gè)用于計(jì)算平方的函數(shù)例如>>> square(2)4>>> square(3)9>>> square(-3)9>>> square(0)0'''return x * 2 # ①、故意寫錯(cuò)的return x ** 2 class User:'''定義一個(gè)代表用戶的類,該類包含如下兩個(gè)屬性:name - 代表用戶的名字age - 代表用戶的年齡例如>>> u = User('fkjava', 9)>>> u.name'fkjava'>>> u.age9>>> u.say('i love python')'fkjava說: i love python''''def __init__(self, name, age):self.name = nameself.name = 'fkit' # ②、故意寫錯(cuò)的self.age = agedef say(self, content):return self.name + '說: ' + content if __name__=='__main__':import doctestdoctest.testmod()#單元測試邏輯覆蓋 def test (a, b, m):if a > 10 and b == 0:m = a + bif a == 20 or m > 15:m += 1 ''' 一、語句覆蓋:每條語句都至少執(zhí)行一次 a=20,b=0,m=3 兩真 二、判定(邊)覆蓋/分支覆蓋:每個(gè)判斷分支取真取假各至少執(zhí)行一次(a>10與b==0是同一分支) a=20,b=0,m=3 兩真 a=10,b=0,m=3 兩假 三、條件覆蓋:每個(gè)判斷中每個(gè)條件的可能取值都至少滿足一次(a>10與b==0是兩個(gè)條件) a=20,b=1,m=10 先假再真 a=9,b=0,m=20 先假再真 四、判定-條件覆蓋:每個(gè)條件所有可能的組合至少出現(xiàn)一次 a=20,b=0,m=3 兩真 a=20,b=1,m=10 先假再真 a=10,b=0,m=20 兩假 a=1,b=2,m=3 兩假 五、路徑覆蓋:覆蓋所有路徑 a=20,b=0,m=3 兩真 a=5,b=0,m=2 兩假 a=20,b=1,m=10 先假再真 a=20,b=0,m=7 先真再假 '''#測試用類例 #fk_math.py def one_equation(a , b):'''求一元一次方程a * x + b = 0的解參數(shù)a - 方程中變量的系數(shù)參數(shù)b - 方程中的常量返回 方程的解'''# 如果a = 0,則方程無法求解if a == 0:raise ValueError("參數(shù)錯(cuò)誤")# 返回方程的解else: # return -b / a # ①return b / a def two_equation(a , b , c):'''求一元二次方程a * x * x + b * x + c = 0的解參數(shù)a - 方程中變量二次冪的系數(shù)參數(shù)b - 方程中變量的系數(shù)參數(shù)c - 方程中的常量返回 方程的根'''if a == 0:raise ValueError("參數(shù)錯(cuò)誤")# 如果a == 0,變成一元一次方程elif b * b - 4 * a * c < 0:raise ValueError("方程在有理數(shù)范圍內(nèi)無解")elif b * b - 4 * a * c == 0:return -b / (2 * a)# 方程有唯一的解else:r1 = (-b + (b * b - 4 * a * c) ** 0.5) / 2 / ar2 = (-b - (b * b - 4 * a * c) ** 0.5) / 2 / areturn r1, r2# 方程的兩個(gè)解 #test_fk_math.py import unittest from fk_math import * class TestFkMath(unittest.TestCase):def test_one_equation(self):# 測試一元一次方程的求解self.assertEqual(one_equation(5 , 9) , -1.8)# 斷言該方程求解應(yīng)該為-1.8self.assertTrue(one_equation(4 , 10) == -2.5 , .00001)# 斷言該方程求解應(yīng)該為-2.5self.assertTrue(one_equation(4 , -27) == 27 / 4)# 斷言該方程求解應(yīng)該為27/4with self.assertRaises(ValueError):one_equation(0 , 9)# 斷言當(dāng)a == 0時(shí)的情況,斷言引發(fā)ValueErrordef test_two_equation(self):# 測試一元二次方程的求解self.assertCountEqual(two_equation(1 , -3 , 2), (1.0, 2.0), '求解出錯(cuò)')self.assertCountEqual(two_equation(2 , -7 , 6), (1.5, 2.0), '求解出錯(cuò)')self.assertEqual(two_equation(1 , -4 , 4), 2.0, '求解出錯(cuò)')# 斷言只有一個(gè)解的情形with self.assertRaises(ValueError):two_equation(0, 9, 3)# 斷言當(dāng)a == 0時(shí)的情況,斷言引發(fā)ValueErrorwith self.assertRaises(ValueError):two_equation(4, 2, 3)# 斷言引發(fā)ValueError if __name__ == '__main__':unittest.main()#測試包與運(yùn)行器(就是把前面的測試用例組合起來) #hello.py def say_hello():return "Hello World." def add(nA, nB):return nA + nB #test_hello.py import unittest from hello import * class TestHello(unittest.TestCase):def test_say_hello(self):self.assertEqual(say_hello() , "Hello World.")def test_add(self):self.assertEqual(add(3, 4) , 7)self.assertEqual(add(0, 4) , 4)self.assertEqual(add(-3, 0) , -3) #suite_test.py import unittest from test_fk_math import TestFkMath from test_hello import TestHello test_cases = (TestHello, TestFkMath) def whole_suite():loader = unittest.TestLoader()# 創(chuàng)建測試加載器suite = unittest.TestSuite()# 創(chuàng)建測試包for test_class in test_cases:# 遍歷所有測試類tests = loader.loadTestsFromTestCase(test_class)# 從測試類中加載測試用例suite.addTests(tests)# 將測試用例添加到測試包中return suite if __name__ == '__main__':with open('fk_test_report.txt', 'a') as f:runner = unittest.TextTestRunner(verbosity=2, stream=f)#創(chuàng)建測試運(yùn)行器(TestRunner),測試報(bào)告輸出到文件中runner.run(whole_suite())#測試 #第十七章:pyinstaller #Python_test2.py文件 def say_hello(name):return name + ",您好!"#Python_test3.py文件 from Python_test2 import * def main():print('程序開始執(zhí)行')print(say_hello('孫悟空')) # 增加調(diào)用main()函數(shù) if __name__ == '__main__':main()#命令行的代碼 #pyinstaller -F F:\ProjectPython\hello_test2\Python_test3.py #-F表示生成一個(gè)大EXE文件,-D表示生成一個(gè)目錄(動態(tài)重定位),加-w取消命令行 #-n NAME或-name NAME可以指定項(xiàng)目名字,如果省略則第一個(gè)腳本的主文件名將作為spec名字(其實(shí)就是main.py,你在開發(fā)的時(shí)候把這個(gè)主程序入口的py文件命名好就行了,例如tank_game.py則最后就會生成tank_game.exe) #現(xiàn)在還未知道如何改圖標(biāo) #第十八章:pygame import pygame def main():pygame.init() #初始化screen=pygame.display.set_mode((1024,640)) #開窗口pygame.display.set_caption("tank game") #定標(biāo)題background=pygame.Surface(screen.get_size())#獲大小background=background.convert() #屏幕轉(zhuǎn)像素background.fill((100,100,100)) #白色填充clock=pygame.time.Clock() #開定時(shí)器running=True #運(yùn)行標(biāo)志while running: #主程序大循環(huán)clock.tick(30) #最大每秒30幀for event in pygame.event.get(): #檢測退出信息if event.type==pygame.QUIT: #如果有的話running=False #更改標(biāo)志位screen.blit(background,(0,0)) #位塊傳送把背景回到左上角#鼠標(biāo)事件buttons=pygame.mouse.get_pressed() #獲鼠標(biāo)按下事件if buttons[0]:print(pygame.mouse.get_pos()) #按左鍵輸出坐標(biāo)#鍵盤事件keys=pygame.key.get_pressed() #獲鍵盤按下事件if keys[pygame.K_SPACE]:print('space') #按下空格輸出space#繪圖:畫矩形(在screen上畫,[r,g,b],[左上角x,y,長,寬],線寬),線寬取0是填充pygame.draw.rect(screen,[255,0,0],[600,600,10,10],0)#貼圖maps = pygame.image.load('GJL.png') #獲取圖片screen.blit(maps,(0,0)) #貼到screen的左上角pygame.display.update() #更新顯示pygame.quit() #退出游戲 main()''' KeyASCII ASCII 描述 K_BACKSPACE \b 退格鍵(Backspace) K_TAB \t 制表鍵(Tab) K_CLEAR 清楚鍵(Clear) K_RETURN \r 回車鍵(Enter) K_PAUSE 暫停鍵(Pause) K_ESCAPE ^[ 退出鍵(Escape) K_SPACE 空格鍵(Space) K_EXCLAIM ! 感嘆號(exclaim) K_QUOTEDBL " 雙引號(quotedbl) K_HASH # 井號(hash) K_DOLLAR $ 美元符號(dollar) K_AMPERSAND & and 符號(ampersand) K_QUOTE ' 單引號(quote) K_LEFTPAREN ( 左小括號(left parenthesis) K_RIGHTPAREN ) 右小括號(right parenthesis) K_ASTERISK * 星號(asterisk) K_PLUS + 加號(plus sign) K_COMMA , 逗號(comma) K_MINUS - 減號(minus sign) K_PERIOD . 句號(period) K_SLASH / 正斜杠(forward slash) K_0 0 0 K_1 1 1 K_2 2 2 K_3 3 3 K_4 4 4 K_5 5 5 K_6 6 6 K_7 7 7 K_8 8 8 K_9 9 9 K_COLON : 冒號(colon) K_SEMICOLON ; 分號(semicolon) K_LESS < 小于號(less-than sign) K_EQUALS = 等于號(equals sign) K_GREATER > 大于號(greater-than sign) K_QUESTION ? 問號(question mark) K_AT @ at 符號(at) K_LEFTBRACKET [ 左中括號(left bracket) K_BACKSLASH \ 反斜杠(backslash) K_RIGHTBRACKET ] 右中括號(right bracket) K_CARET ^ 脫字符(caret) K_UNDERSCORE _ 下劃線(underscore) K_BACKQUOTE ` 重音符(grave) K_a a a K_b b b K_c c c K_d d d K_e e e K_f f f K_g g g K_h h h K_i i i K_j j j K_k k k K_l l l K_m m m K_n n n K_o o o K_p p p K_q q q K_r r r K_s s s K_t t t K_u u u K_v v v K_w w w K_x x x K_y y y K_z z z K_DELETE 刪除鍵(delete) K_KP0 0(小鍵盤) K_KP1 1(小鍵盤) K_KP2 2(小鍵盤) K_KP3 3(小鍵盤) K_KP4 4(小鍵盤) K_KP5 5(小鍵盤) K_KP6 6(小鍵盤) K_KP7 7(小鍵盤) K_KP8 8(小鍵盤) K_KP9 9(小鍵盤) K_KP_PERIOD . 句號(小鍵盤) K_KP_DIVIDE / 除號(小鍵盤) K_KP_MULTIPLY * 乘號(小鍵盤) K_KP_MINUS - 減號(小鍵盤) K_KP_PLUS + 加號(小鍵盤) K_KP_ENTER \r 回車鍵(小鍵盤) K_KP_EQUALS = 等于號(小鍵盤) K_UP 向上箭頭(up arrow) K_DOWN 向下箭頭(down arrow) K_RIGHT 向右箭頭(right arrow) K_LEFT 向左箭頭(left arrow) K_INSERT 插入符(insert) K_HOME Home 鍵(home) K_END End 鍵(end) K_PAGEUP 上一頁(page up) K_PAGEDOWN 下一頁(page down) K_F1 F1 K_F2 F2 K_F3 F3 K_F4 F4 K_F5 F5 K_F6 F6 K_F7 F7 K_F8 F8 K_F9 F9 K_F10 F10 K_F11 F11 K_F12 F12 K_F13 F13 K_F14 F14 K_F15 F15 K_NUMLOCK 數(shù)字鍵盤鎖定鍵(numlock) K_CAPSLOCK 大寫字母鎖定鍵(capslock) K_SCROLLOCK 滾動鎖定鍵(scrollock) K_RSHIFT 右邊的 shift 鍵(right shift) K_LSHIFT 左邊的 shift 鍵(left shift) K_RCTRL 右邊的 ctrl 鍵(right ctrl) K_LCTRL 左邊的 ctrl 鍵(left ctrl) K_RALT 右邊的 alt 鍵(right alt) K_LALT 左邊的 alt 鍵(left alt) K_RMETA 右邊的元鍵(right meta) K_LMETA 左邊的元鍵(left meta) K_LSUPER 左邊的 Window 鍵(left windows key) K_RSUPER 右邊的 Window 鍵(right windows key) K_MODE 模式轉(zhuǎn)換鍵(mode shift) K_HELP 幫助鍵(help) K_PRINT 打印屏幕鍵(print screen) K_SYSREQ 魔術(shù)鍵(sysrq) K_BREAK 中斷鍵(break) K_MENU 菜單鍵(menu) K_POWER 電源鍵(power) K_EURO 歐元符號(euro) ''' 第十九章:matplotlib #入門 import matplotlib.pyplot as plt import numpy as np plt.figure() plt.subplot(2,1,1)#將整個(gè)figure分成兩行兩列,并將下面圖形放在第4個(gè)網(wǎng)格 x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] ln1,=plt.plot(x_data,y_data,color='red',linewidth=2.0,linestyle='--',label='cj')#折線顏色、線寬和樣式 ln2,=plt.plot(x_data,y_data2,color='blue',linewidth=3.0,linestyle='-.',label='gjl')#-實(shí)線--虛線:點(diǎn)線-.點(diǎn)虛線 plt.legend(loc='lower right')#調(diào)用legend函數(shù)設(shè)置圖例,location默認(rèn)是'best'自動選擇最佳位置 plt.xlabel('year') plt.ylabel('salary') plt.title('gogogo') #plt.yticks([50000,70000,100000],[r'A',r'B',r'C'])#這行出現(xiàn)就會代替Y坐標(biāo)值 #plt.show()# 調(diào)用show()函數(shù)顯示圖形 ax = plt.gca()#返回的是axis坐標(biāo)軸 ax.spines['bottom'].set_position(('data',70000))#設(shè)置坐標(biāo)軸的bottom處的位置是data=70000處 #ax.yaxis.set_ticks_position('left')#設(shè)置坐標(biāo)軸的Y軸的位置在left處,可以無視,默認(rèn)就是這樣 #ax.xaxis.set_ticks_position('bottom')#設(shè)置坐標(biāo)軸的X軸的的位置在bottom處,可以無視,默認(rèn)就是這樣 #ax.spines['right'].set_color('red')#設(shè)置右邊坐標(biāo)軸線的顏色(設(shè)置為none表示不顯示),可以無視,沒啥用 #ax.spines['top'].set_color('blue')#設(shè)置頂部坐標(biāo)軸線的顏色(設(shè)置為none表示不顯示),可以無視,沒啥用 plt.subplot(2,1,2)#將整個(gè)figure分成兩行兩列,第三個(gè)參數(shù)表示下面的圖形放在第1個(gè)網(wǎng)格 x_data=np.linspace(-np.pi,np.pi,64,endpoint=True)#利用np.pi線性均分成64個(gè)點(diǎn) plt.plot(x_data, np.sin(x_data))#開始繪制正弦曲線,注意此時(shí)的plt是畫在212位置的 plt.gca().spines['right'].set_color('none') plt.gca().spines['top'].set_color('none') plt.gca().spines['bottom'].set_position(('data', 0)) plt.gca().spines['left'].set_position(('data', 0)) plt.title('sin') plt.show()#子圖 import matplotlib.pyplot as plt import numpy as np import matplotlib.gridspec as gridspec plt.figure() x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)#取生成x點(diǎn) gs = gridspec.GridSpec(2, 3)# 將繪圖區(qū)域分成2行3列 ax1 = plt.subplot(gs[0, :])# 指定ax1占用第零行 ax2 = plt.subplot(gs[1, 0])# 指定ax1占用第一行的第零格 ax3 = plt.subplot(gs[1, 1:3])# 指定ax1占用一行的第二、三格 ax1.plot(x_data, np.sin(x_data))# 繪制正弦曲線 ax1.spines['right'].set_color('none') ax1.spines['top'].set_color('none') ax1.spines['bottom'].set_position(('data', 0)) ax1.spines['left'].set_position(('data', 0)) ax1.set_title('sin') ax2.plot(x_data, np.cos(x_data))# 繪制余弦曲線 ax2.spines['right'].set_color('none') ax2.spines['top'].set_color('none') ax2.spines['bottom'].set_position(('data', 0)) ax2.spines['left'].set_position(('data', 0)) ax2.set_title('cos') ax3.plot(x_data, np.tan(x_data))# 繪制正切曲線 ax3.spines['right'].set_color('none') ax3.spines['top'].set_color('none') ax3.spines['bottom'].set_position(('data', 0)) ax3.spines['left'].set_position(('data', 0)) ax3.set_title('tan') plt.show()#餅圖 import matplotlib.pyplot as plt data=[0.16881, 0.14966, 0.07471, 0.06992,0.04762, 0.03541, 0.02925, 0.02411, 0.02316, 0.01409, 0.36326] labels=['Java','C','C++','Python','Visual Basic .NET','C#','PHP','JavaScript','SQL','Assembly langugage','other'] explode = [0, 0, 0, 0.3, 0, 0, 0, 0, 0, 0, 0]# 將第4個(gè)語言(Python)分離出來 colors=['red', 'pink', 'magenta','purple','orange'] # 使用自定義顏色 plt.axes(aspect='equal')#正圓 plt.xlim(0,8)#邊框大小 plt.ylim(0,8)#邊框大小 plt.pie(x = data, # 繪圖數(shù)據(jù)labels=labels, # 添加編程語言標(biāo)簽explode=explode, # 突出顯示Pythoncolors=colors, # 設(shè)置餅圖的自定義填充色autopct='%.3f%%', # 設(shè)置百分比的格式,此處保留3位小數(shù)pctdistance=0.8, # 設(shè)置百分比標(biāo)簽與圓心的距離labeldistance = 1.15, # 設(shè)置標(biāo)簽與圓心的距離startangle = 180, # 設(shè)置餅圖的初始角度center = (4, 4), # 設(shè)置餅圖的圓心(相當(dāng)于X軸和Y軸的范圍)radius = 3.8, # 設(shè)置餅圖的半徑(相當(dāng)于X軸和Y軸的范圍)counterclock = False, # 是否逆時(shí)針,這里設(shè)置為順時(shí)針方向wedgeprops = {'linewidth': 1, 'edgecolor':'green'},# 設(shè)置餅圖內(nèi)外邊界的屬性值textprops = {'fontsize':12, 'color':'black'}, # 設(shè)置文本標(biāo)簽的屬性值frame = 1) # 是否顯示餅圖的圓圈,此處設(shè)為顯示 plt.xticks(()) plt.yticks(()) plt.title('2018-08 languagu rank') plt.show()#豎柱狀圖 import matplotlib.pyplot as plt import numpy as np x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] bar_width=0.3 #range(len(x_data)就是0、1、2控制中心坐標(biāo)故np.arange(len(x_data))是左柱中心坐標(biāo),加+bar_width就是右柱中心坐標(biāo) plt.bar(x=range(len(x_data)),height=y_data,label='CJ',color='steelblue', alpha=0.8, width=bar_width) plt.bar(x=np.arange(len(x_data))+bar_width+0.05, height=y_data2,label='GJL', color='indianred', alpha=0.8, width=bar_width) for x,y in enumerate(y_data):plt.text(x,y,'%s'%y,ha='center',va='bottom')#x,y是坐標(biāo),'%s'%y是內(nèi)容 for x,y in enumerate(y_data2):plt.text(x+bar_width,y,'%s'%y,ha='center',va='top')#ha水平對齊, va垂直對齊 plt.xticks(np.arange(len(x_data))+bar_width/2, x_data)# 為X軸設(shè)置刻度值 plt.title("CJ&GJL")#設(shè)置標(biāo)題 plt.xlabel("year")#X標(biāo)簽 plt.ylabel("salary")#Y標(biāo)答 plt.legend()#圖例 plt.show() #橫柱狀圖 import matplotlib.pyplot as plt import numpy as np x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] bar_width=0.3 plt.barh(y=range(len(x_data)), width=y_data, label='CJ',color='steelblue', alpha=0.8, height=bar_width) plt.barh(y=np.arange(len(x_data))+bar_width, width=y_data2,label='GJL', color='indianred', alpha=0.8, height=bar_width) for y, x in enumerate(y_data):plt.text(x+5000,y-bar_width/2,'%s'%x,ha='center',va='bottom') for y, x in enumerate(y_data2):plt.text(x+5000,y+bar_width/2,'%s'%x,ha='center',va='bottom') plt.yticks(np.arange(len(x_data))+bar_width/2, x_data)# 為Y軸設(shè)置刻度值 plt.title("CJ&GJL")#設(shè)置標(biāo)題 plt.xlabel("year")#X標(biāo)簽 plt.ylabel("salary")#Y標(biāo)答 plt.legend()#圖例 plt.show()#散點(diǎn)圖 import matplotlib.pyplot as plt import numpy as np plt.figure() x_data = np.linspace(-np.pi, np.pi, 64, endpoint=True)# 定義從-pi到pi之間的數(shù)據(jù),平均取64個(gè)數(shù)據(jù)點(diǎn) plt.scatter(x_data, #x值np.sin(x_data), #y值c='purple', #設(shè)置點(diǎn)的顏色s=50, #設(shè)置點(diǎn)半徑alpha = 0.5, #設(shè)置透明度marker='p', #設(shè)置使用五邊形標(biāo)記linewidths=1, #設(shè)置邊框的線寬edgecolors=['green', 'yellow']) # 設(shè)置邊框的顏色 plt.scatter(x_data[0], np.sin(x_data)[0], c='red',s=150, alpha = 1) plt.scatter(x_data[63], np.sin(x_data)[63], c='black',s=150,alpha = 1) plt.gca().spines['right'].set_color('none') plt.gca().spines['top'].set_color('none') plt.gca().spines['bottom'].set_position(('data', 0)) plt.gca().spines['left'].set_position(('data', 0)) plt.title('sin') plt.show()#等高線圖 import matplotlib.pyplot as plt import numpy as np delta = 0.025 x=np.arange(-3.0,3.0,delta)#生成代表X軸數(shù)據(jù)的列表 y=np.arange(-2.0,2.0,delta)#生成代表Y軸數(shù)據(jù)的列表 X,Y=np.meshgrid(x, y)#對x、y數(shù)據(jù)執(zhí)行網(wǎng)格化 Z1=np.exp(-X**2-Y**2) Z2=np.exp(-(X-1)**2-(Y-1)**2) Z=(Z1-Z2)*2# 計(jì)算Z軸數(shù)據(jù)(高度數(shù)據(jù)) plt.contourf(x,y,Z,16,alpha=0.75,cmap='rainbow')#使用顏色映射來區(qū)分16種不同高度的區(qū)域 C=plt.contour(x,y,Z,16,#繪制等高線colors='black',#指定等高線的顏色linewidth=0.5)#指定等高線的線寬 plt.clabel(C, inline = True, fontsize = 10)#繪制等高線數(shù)據(jù) plt.xticks(())#去除坐標(biāo)軸 plt.yticks(())#去除坐標(biāo)軸 plt.title("contour") plt.xlabel("x") plt.ylabel("y") plt.show()#3D圖形 import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.mplot3d import Axes3D fig = plt.figure(figsize=(12, 8)) ax = Axes3D(fig) delta = 0.125 x = np.arange(-3.0, 3.0, delta)# 生成代表X軸數(shù)據(jù)的列表 y = np.arange(-2.0, 2.0, delta)# 生成代表Y軸數(shù)據(jù)的列表 X, Y = np.meshgrid(x, y)# 對x、y數(shù)據(jù)執(zhí)行網(wǎng)格化 Z1 = np.exp(-X**2 - Y**2) Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2) Z = (Z1 - Z2) * 2# 計(jì)算Z軸數(shù)據(jù)(高度數(shù)據(jù)) ax.plot_surface(X, Y, Z, # 繪制3D圖形rstride=1, # rstride(row)指定行的跨度cstride=1, # cstride(column)指定列的跨度cmap=plt.get_cmap('rainbow')) # 設(shè)置顏色映射 ax.set_zlim(-2, 2)# 設(shè)置Z軸范圍 plt.title("3D")# 設(shè)置標(biāo)題 plt.show()#pygal:實(shí)在太簡單了,缺點(diǎn)是必須用瀏覽器看 import pygal#例一柱圖 y_data = [58000, 60200, 63000, 71000, 84000, 90500, 107000] y_data2 = [52000, 54200, 51500,58300, 56800, 59500, 62700] bar = pygal.Bar()# 創(chuàng)建pygal.Bar對象(柱狀圖) bar.add('Java', y_data)# 添加兩組代表?xiàng)l柱的數(shù)據(jù) bar.add('Android', y_data2) bar.render_to_file('fk_books.svg')# 添加兩組代表?xiàng)l柱的數(shù)據(jù)#例二柱圖加強(qiáng)版 x_data = ['2011', '2012', '2013', '2014', '2015', '2016', '2017'] bar.x_labels = x_data# 設(shè)置X軸的刻度值 bar.title = '銷量' bar.x_title = '年份' bar.y_title = '銷量' bar.x_label_rotation = 45# 設(shè)置X軸的刻度值旋轉(zhuǎn)45度 bar.legend_at_bottom = True# 設(shè)置將圖例放在底部 bar.margin = 35# 設(shè)置數(shù)據(jù)圖四周的頁邊距,也可通過margin_bottom、margin_left、margin_right、margin_top只設(shè)置單獨(dú)一邊的頁邊距 bar.show_y_guides=False# 隱藏Y軸上的網(wǎng)格線 bar.show_x_guides=True# 顯示X軸上的網(wǎng)格線 bar.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#例三折線圖 line = pygal.Line()# 創(chuàng)建pygal.Line對象(折線圖) line.add('Java', y_data)# 添加兩組代表折線的數(shù)據(jù) line.add('Android', y_data2) line.x_labels = x_data# 設(shè)置X軸的刻度值 line.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置Y軸的刻度值 line.title = '銷量' line.x_title = '年份' line.y_title = '銷量' line.legend_at_bottom = True# 設(shè)置將圖例放在底部 line.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#水平柱狀圖 horizontal_bar = pygal.HorizontalBar()# 創(chuàng)建pygal.HorizontalBar對象(水平柱狀圖) horizontal_bar.add('Java', y_data)# 添加兩組數(shù)據(jù) horizontal_bar.add('Android', y_data2) horizontal_bar.x_labels = x_data# 設(shè)置Y軸的刻度值(注意xy這里掉亂說的,有點(diǎn)迷糊) horizontal_bar.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置X軸的刻度值 horizontal_bar.title = '銷量' horizontal_bar.x_title = '銷量' horizontal_bar.y_title = '年份' horizontal_bar.legend_at_bottom = True# 設(shè)置將圖例放在底部 horizontal_bar.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#水平折線圖 horizontal_line = pygal.HorizontalLine()# 創(chuàng)建pygal.HorizontalLine對象(水平折線圖) horizontal_line.add('Java', y_data)# 添加兩組代表折線的數(shù)據(jù) horizontal_line.add('Android', y_data2) horizontal_line.x_labels = x_data# 設(shè)置Y軸(確實(shí)如此)的刻度值 horizontal_line.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置X軸(確實(shí)如此)的刻度值 horizontal_line.title = '銷量' horizontal_line.x_title = '銷量' horizontal_line.y_title = '年份' horizontal_line.legend_at_bottom = True# 設(shè)置將圖例放在底部 horizontal_line.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#疊加柱狀圖 stacked_bar = pygal.StackedBar() stacked_bar.add('Java', y_data)# 添加兩組數(shù)據(jù) stacked_bar.add('Android', y_data2) stacked_bar.x_labels = x_data# 設(shè)置X軸的刻度值 stacked_bar.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置Y軸的刻度值 stacked_bar.title = '銷量' stacked_bar.x_title = '銷量' stacked_bar.y_title = '年份' stacked_bar.legend_at_bottom = True# 設(shè)置將圖例放在底部 stacked_bar.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#疊加折線圖 stacked_line = pygal.StackedLine() stacked_line.add('Java', y_data)# 添加兩組數(shù)據(jù) stacked_line.add('Android', y_data2) stacked_line.x_labels = x_data# 設(shè)置X軸的刻度值 stacked_line.y_labels = [20000, 40000, 60000, 80000, 100000]# 重新設(shè)置Y軸的刻度值 stacked_line.title = '銷量' stacked_line.x_title = '銷量' stacked_line.y_title = '年份' stacked_line.legend_at_bottom = True# 設(shè)置將圖例放在底部 stacked_line.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#點(diǎn)圖 dot = pygal.Dot() dot.dots_size = 5 dot.add('Java', y_data)# 添加兩組數(shù)據(jù) dot.add('Android', y_data2) dot.x_labels = x_data# 設(shè)置X軸的刻度值 dot.y_labels = ['Java', 'Android']# 重新設(shè)置Y軸的刻度值 dot.y_label_rotation = 45# 設(shè)置Y軸刻度值的旋轉(zhuǎn)角度 dot.title = '銷量' dot.x_title = '年份' dot.legend_at_bottom = True# 設(shè)置將圖例放在底部 dot.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#餅圖 data=[0.16881,0.14966,0.07471,0.06992,0.04762,0.03541,0.02925,0.02411,0.02316,0.01409,0.36326] labels=['Java','C','C++','Python','Visual Basic .NET','C#','PHP','JavaScript','SQL','Assembly langugage','其他']# 準(zhǔn)備標(biāo)簽 pie = pygal.Pie()# 創(chuàng)建pygal.Pie對象(餅圖) for i, per in enumerate(data): pie.add(labels[i], per)# 采用循環(huán)為餅圖添加數(shù)據(jù) pie.title = '2018年8月編程語言' pie.legend_at_bottom = True# 設(shè)置將圖例放在底部 pie.inner_radius = 0.4# 設(shè)置內(nèi)圈的半徑長度 pie.half_pie = True# 創(chuàng)建半圓數(shù)據(jù)圖 pie.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#儀表圖 gauge = pygal.Gauge()# 創(chuàng)建pygal.Gauge對象(儀表圖) gauge.range = [0, 1] for i, per in enumerate(data):gauge.add(labels[i], per)# 采用循環(huán)為儀表圖添加數(shù)據(jù) gauge.title = '2018年8月編程語言' gauge.legend_at_bottom = True# 設(shè)置將圖例放在底部 gauge.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#雷達(dá)圖 data = [[5, 4.0, 5, 5, 5],# 準(zhǔn)備數(shù)據(jù)[4.8, 2.8, 4.8, 4.8, 4.9],[4.5, 2.9, 4.6, 4.0, 4.9],[4.0, 4.8, 4.9, 4.0, 5],[3.0, 4.2, 2.3, 3.5, 2],[4.8, 4.3, 3.9, 3.0, 4.5]] labels = ['Java', 'C', 'C++', 'Python','C#', 'PHP']# 準(zhǔn)備標(biāo)簽 rader = pygal.Radar()# 創(chuàng)建pygal.Radar對象(雷達(dá)圖) for i, per in enumerate(labels):rader.add(labels[i], data[i])# 采用循環(huán)為雷達(dá)圖添加數(shù)據(jù) rader.x_labels = ['平臺健壯性', '語法易用性', '社區(qū)活躍度','市場份額', '未來趨勢'] rader.title = '編程語言對比圖' rader.dots_size = 8# 控制各數(shù)據(jù)點(diǎn)的大小 rader.legend_at_bottom = True# 設(shè)置將圖例放在底部 rader.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#csv import csv import pygal from datetime import datetime from datetime import timedelta with open('guangzhou-2017.csv') as f:# 打開文件reader = csv.reader(f)# 創(chuàng)建cvs文件讀取器header_row = next(reader)# 讀取第一行,這行是表頭數(shù)據(jù)。print(header_row)shades, sunnys, cloudys, rainys = 0, 0, 0, 0# 準(zhǔn)備展示的數(shù)據(jù)prev_day = datetime(2016, 12, 31)for row in reader:try:cur_day = datetime.strptime(row[0], '%Y-%m-%d')# 將第一列的值格式化為日期description = row[3]except ValueError:print(cur_day, '數(shù)據(jù)出現(xiàn)錯(cuò)誤')else:diff = cur_day - prev_day# 計(jì)算前、后兩天數(shù)據(jù)的時(shí)間差if diff != timedelta(days=1):# 如果前、后兩天數(shù)據(jù)的時(shí)間差不是相差一天,說明數(shù)據(jù)有問題print('%s之前少了%d天的數(shù)據(jù)' % (cur_day, diff.days - 1))prev_day = cur_day if '陰' in description:shades += 1elif '晴' in description:sunnys += 1elif '云' in description:cloudys += 1elif '雨' in description:rainys += 1else:print(description) pie = pygal.Pie()# 創(chuàng)建pygal.Pie對象(餅圖) pie.add("陰", shades)# 為餅圖添加數(shù)據(jù) pie.add("晴", sunnys) pie.add("多云", cloudys) pie.add("雨", rainys) pie.title = '2017年廣州天氣匯總' pie.legend_at_bottom = True# 設(shè)置將圖例放在底部 pie.render_to_file('fk_books.svg')# 指定將數(shù)據(jù)圖輸出到SVG文件中#json import json with open('gdp_json.json') as f:gpd_list = json.load(f) for gpd_dict in gpd_list:# 遍歷列表的每個(gè)元素,每個(gè)元素是一個(gè)GDP數(shù)據(jù)項(xiàng)if gpd_dict['Year']==2016 and gpd_dict['Country Code']=='CHN':#中國2016年GDPprint(gpd_dict['Country Name'], gpd_dict['Value']) #第二十章:自動登陸及刷閱讀量 from selenium import webdriver from time import sleep url='http://www.51cto.com'#定義網(wǎng)址 browser=webdriver.Chrome()#打開瀏覽器并獲句柄 browser.maximize_window() #最大化窗口 browser.get(url) #打開URL browser.find_element_by_xpath('//*[@id="login_status"]/a[1]').click()#點(diǎn)擊登陸按鈕 browser.find_element_by_xpath('//*[@id="loginform-username"]').clear()#帳戶框清空 browser.find_element_by_xpath('//*[@id="loginform-username"]').send_keys('13690670863')#輸入帳號 browser.find_element_by_xpath('//*[@id="loginform-password"]').clear()#密碼框清空 browser.find_element_by_xpath('//*[@id="loginform-password"]').send_keys('abcde123456789')#輸入密碼 sleep(3)#延時(shí)三秒 browser.find_element_by_xpath('//*[@id="login-form"]/div[3]/input').click()#點(diǎn)擊確定 sleep(3)#延時(shí)三秒 browser.quit()#退出
補(bǔ)充一句:spyder中一鍵注釋快捷鍵是ctrl+1
總結(jié)
以上是生活随笔為你收集整理的疯狂python讲义学习笔记——中十章完结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 动态改变button样式
- 下一篇: 飞上“云端”的OA系统:什么是OA系统的