Python 作業 1
現有一個游戲系統的日志文件,記錄內容的字符串 的格式 如下所示
A girl come in, the name is Jack, level 955;
其中包含的 the name is 后面會跟着人名,隨后緊跟一個逗號, 這是固定的格式。
其它部分可能都是會變化的,比如,可能是下面這些
A old lady come in, the name is Mary, level 94454
A pretty boy come in, the name is Patrick, level 194
請大家實現一個函數,名為getName,如下所示
def getName(srcStr): 函數體
該函數的參數srcStr 是上面所描述的格式字符串(只處理一行),該函數需要將其中的人名獲取出來,並返回
比如 調用 getName('A old lady come in, the name is Mary, level 94454')
返回結果應該是 'Mary'
def getName(srcStr): return srcStr.split('the name is ')[1].split(',')[0]
Python 編程作業 02
請實現一個程序,實現如下需求點
1.程序開始的時候提示用戶輸入學生年齡信息 格式如下:
Jack Green , 21 ; Mike Mos, 9; 我們假設 用戶輸入 上面的信息,必定會遵守下面的規則: 學生信息之間用分號隔開(分號前后可能有不定數量的空格), 每個學生信息里的 姓名和 年齡之間用 逗號隔開(逗號前后可能有不定數量的空格) 2. 程序隨后將輸入的學生信息分行顯示,格式如下 Jack Green : 21; Mike Mos : 09; 學生的姓名要求左對齊,寬度為20, 年齡信息右對齊,寬度為2位,不足前面補零
請再實現一個程序,實現如下需求點
1.下面的log變量記錄了雲服務器上 當天上傳的文件信息
其中第一列是文件名,第二列是文件大小
請編寫一個程序,統計出不同類型的 文件的大小總和
比如:
jpeg 9988999 json 324324 png 2423233 ---------------------------------- log = ''' f20180111014341/i_51a7hC3W.jpeg 169472 FrITJxleSP7wUD-MWw-phL_KP6Eu 15156063244230469 image/jpeg 0 f20180111014341/j_R0Hpl4EG.json 1036 ForGzwzV3e-uR3_UzvppJs1VgfQG 15156064773253144 application/json 0 f20180111020739/i_0TDKs0rD.jpeg 169472 FrITJxleSP7wUD-MWw-phL_KP6Eu 15156076847077556 image/jpeg 0 f20180111020739/j_JFO6xiir.json 1040 FmUhTchdLOd7LBoE8OXzPLDKcW60 15156077904192983 application/json 0 f20180111090619/i_1BwNksbL.jpg 49634 FtXBGmipcDha-67WQgGQR5shEBu2 15156329458714950 image/jpeg 0 f20180111090619/i_3BKlsRaZ.jpg 30152 FoWfMSuqz4TEQl5FT-FY5wqu5NGf 15156330575626044 image/jpeg 0 f20180111090619/i_5XboXSKh.jpg 40238 Fl84WaBWThHovIBsQaNFoIaPZcWh 15156329453409855 image/jpeg 0 f20180111090619/i_6DiYSBKp.jpg 74017 FrYG3icChRmFGnWQK6rYxa88KuQI 15156329461803290 image/jpeg 0 f20180111090619/i_76zaF2IM.jpg 38437 Fui8g5OrJh0GQqZzT9wtepfq99lJ 15156334738356648 image/jpeg 0 f20180111090619/i_B6TFYjks.jpg 37953 FleWqlK2W1ZmEgAatAEcm1gpR0kC 15156329464034474 image/jpeg 0 f20180111090619/i_N9eITqj3.jpg 38437 Fui8g5OrJh0GQqZzT9wtepfq99lJ 15156330419595764 image/jpeg 0 f20180111090619/i_QTSNWmA6.jpg 37953 FleWqlK2W1ZmEgAatAEcm1gpR0kC 15156333104224056 image/jpeg 0 f20180111090619/i_XdHcAfh1.jpg 56479 FjLQIQ3GxSEHDfu6tRcMylK1MZ05 15156334227270309 image/jpeg 0 f20180111090619/i_Xyy723MU.jpg 50076 FsfZpQzqu084RUw5NPYW9-Yfam_R 15156334229987458 image/jpeg 0 f20180111090619/i_d8Go0EOv.jpg 30152 FoWfMSuqz4TEQl5FT-FY5wqu5NGf 15156334736228515 image/jpeg 0 f20180111090619/i_diuHmX53.jpg 40591 FuTx1pw4idbKnV5MSvNGxCA5L470 15156333878320713 image/jpeg 0 f20180111090619/i_qQKzheSH.jpg 55858 Fj0A3i8V7fzzOiPQFL79ao15hkN9 15156329456666591 image/jpeg 0 f20180111090619/i_rHL5SYk8.jpg 40238 Fl84WaBWThHovIBsQaNFoIaPZcWh 15156336509742181 image/jpeg 0 f20180111090619/i_xZmQxUbz.jpg 40238 Fl84WaBWThHovIBsQaNFoIaPZcWh 15156333240603466 image/jpeg 0 f20180111090619/i_zBDNgXDv.jpeg 73616 FlgNwq8lypgsxrWs_ksrS_x47SQV 15156334232887875 image/jpeg 0 f20180111090619/j_4mxbEiVh.json 2990 Fpq-3yl3Yr1CadNrJVSDnpeRhQtT 15156331445226898 application/json 0 f20180111090619/j_i1K74768.json 3042 Fl5PpDw1TsZXMuhoq1RUrOeGZ6br 15156335067090003 application/json 0 f20180111095839/i_Q7KMKeda.png 518522 Fl-yB1_ruL2uxZN9k7DjB62h9dYH 15156359599713253 image/png 0 f20180111095839/j_5DpqHolV.json 184 FoYvi7cmSrzuVjUgCRzW5kU95SVo 15156359719719064 application/json 0 f20180111100442/i_No8kToIV.jpg 48975 Fu1cw3f--5Vpz9kLGeJfvljhCtyZ 15156364349642377 image/jpeg 0 f20180111100442/i_P1bkvSeg.jpg 68200 FvYe8vi46TjUKhEy_UwDqLhO6ZsW 15156363800690634 image/jpeg 0 f20180111100442/i_T1AulKcD.jpg 52641 Fj2YzvdC1n_1sF93ZZgrhF3OzOeY 15156364021186365 image/jpeg 0 f20180111100442/i_X8d8BN07.jpg 50770 FivwidMiHbogw77lqgkIKrgmF3eA 15156363969737156 image/jpeg 0 f20180111100442/i_g0wtOsCX.jpg 76656 Fmtixx0mP9CAUTNosjLuYQHL6k0P 15156363448222155 image/jpeg 0 f20180111100442/i_h5OT9324.jpg 72672 FvbIqPLTh2cQHTIBv2akUfahZa_Z 15156364401354652 image/jpeg 0 f20180111100442/i_he8iLYI6.jpg 49399 FjeJvwjwhU-hKZsq66UoBg9_tEJs 15156363907932480 image/jpeg 0 f20180111100442/i_kg29t7Pp.jpg 76293 FuYj__sSeEN7AsXMbxO24Z8Suh8d 15156364156384686 image/jpeg 0 f20180111100442/i_oz1YoBI1.jpg 75620 FkY3xsUMwOI01zgoH1iXXgiQeq6I 15156364089112904 image/jpeg 0 f20180111100442/i_xrOT98on.jpg 50021 Fql7ookM1Rc6V7VairKAfnKe-o9w 15156363856357316 image/jpeg 0 f20180111135114/i_Zqt8Tmoe.png 161629 FlELw59_mV3VqDBLyu1BKN4fIWnx 15156500155209863 image/png 0 f20180111135114/j_uhHoMXKq.json 159 FrypljwAr2LgoLAePBNTUYTUAgDt 15156500200488238 application/json 0 f20180111142119/i_s83iZ2GR.png 92278 Fns8tdh3JCkRmfE_COYEu4o8w03E 15156517082371259 image/png 0 f20180111142119/j_0g45JRth.json 159 Fq1rFwdRguYRXrp61nGZ5TsUG1V- 15156517143375596 application/json 0 f20180111144306/i_yE5TC84E.png 139230 Fjf61ymabEnEvnr5ZMHFjXGCrYlP 15156530038824150 image/png 0 f20180111144306/j_OF4WVtSH.json 159 FqwkKcxfo8jd0jFUyuH4X2CrnE9q 15156530083419530 application/json 0 f20180111150230/i_KtnER4g3.png 120044 FuwOWdrqzcr2-UScem-LzEMgMezs 15156541734892258 image/png 0 f20180111150230/j_xMSUEejY.json 158 FjJr_4deMqFphGaptm-2Pa6wwRP2 15156541771989216 application/json 0 f20180111151741/i_JuSWztB3.jpg 92506 FrIjRevHSi6xv4-NQa2wrHu5a1zQ 15156550875370965 image/jpeg 0 f20180111153550/i_9wWzVenl.gif 769872 FvslKY9JUaCQm-lu02E34tvAP_oG 15156561674621628 image/gif 0 '''
題1 inputStr = input('Please input student age info:') studentInfo = inputStr.split(';') for one in studentInfo: # check if it is valid input if ',' not in one: continue name,age = one.split(',') name = name.strip() age = age.strip() # check is age digit if not age.isdigit(): continue age = int(age) print('%-20s : %02d' % (name, age)) # print('{:20} : {:02}'.format(name, age)) # print(f'{name:20} : {age:02}') 題2 # 記錄各種類型的文件的數量統計,存儲格式如下 # [['jpg',4566],['json',4566]] fileLenTable = [] # 根據文件類型找到記錄對象,進行累加 def putRecordToTable(fileType,fileLen): for one in fileLenTable: if one[0] == fileType: one[1] += fileLen return # 沒有找到,創建一個記錄元素 fileLenTable.append([fileType,fileLen]) return for line in log.split('\n'): if line.strip() == '': continue parts = line.split('\t') name,size = parts[:2] ext = name.split('.')[-1] putRecordToTable(ext,int(size)) print(fileLenTable)
Python 作業 03
請定義一個函數 mySort,參數為一個列表,參數列表中的元素都是整數.
mySort 函數需要將參數列表中的元素按從小到大排序,最終返回一個新的list。
請按下面算法的思路實現函數:
1. 創建一個新的列表newList 2. 先找出所有元素中最小的,append在newList里面 3. 再找出剩余的所有元素中最小的,append在newList里面 4. 依次類推,直到所有的元素都放到newList里面
def sort(inList): newList = [] # 設計一個循環,每個循環做如下事情(直到 inlist 沒有元素): # 找出當前inlist中所有元素中最小curMin的,append在newList里面 # # inList 去掉 curMin while len(inList) > 0: theMin = inList[0] # 記錄當前循環最小元素 minIdx = 0 # 記錄當前最小元素的下標 idx = 0 # 指向當前元素下標 for one in inList: if theMin > one: theMin = one minIdx = idx idx += 1 inList.pop(minIdx) newList.append(theMin) return newList print (sort([1,3,5,7,34,23,55,56,2,3,4]))
Python 作業 5
現有一個數據庫記錄文件(見附件0005_1.txt),保存了學生課程簽到的數據庫記錄。 內容格式如下 ,
('2017-03-13 11:50:09', 271, 131), ('2017-03-14 10:52:19', 273, 131), ('2017-03-13 11:50:19', 271, 126),
每一行記錄保存了學生的一次簽到信息。
每一次簽到信息的記錄,分為三個部分, 分別是簽到時間、簽到課程的id號、簽到學生的id號
要求大家實現下面的函數。其中參數fileName 為 數據庫記錄文件路徑, 輸出結果是將數據庫記錄文件中的學生簽到信息保存在一個字典對象中,並作為返回值返回。
def putInfoToDict(fileName):
要求返回的字典對象的格式是這樣的:
key 是各個學生的id號, value是 該學生的簽到信息
其中value,里面保存着該學生所有簽到的信息
其中每個簽到的信息是字典對象,有兩個元素: key 是lessonid的 記錄課程id,key是checkintime的 記錄簽到時間
比如,對於上面的示例中的3條記錄,相應的返回結果如下:
{
131: [
{'lessonid': 271,'checkintime':'2017-03-13 11:50:09'}, {'lessonid': 273,'checkintime':'2017-03-14 10:52:19'}, ], 126: [ {'lessonid': 271,'checkintime':'2017-03-13 11:50:19'}, ], }
def putInfoToDict(fileName): retDict = {} with open(fileName) as f: lines = f.read().splitlines() for line in lines: # remove '(' and ')' line = line.replace('(','').replace(')','').replace(';','').strip() parts = line.split(',') ciTime = parts[0].strip().replace("'",'') lessonid = int(parts[1].strip()) userid = int(parts[2].strip()) toAdd = {'lessonid':lessonid,'checkintime':ciTime} # if not in, need to create list first if userid not in retDict: retDict[userid] = [] retDict[userid].append(toAdd) # or just #retDict.setdefault(userid,[]).append(toAdd) return retDict ret = putInfoToDict('0005_1.txt') import pprint pprint.pprint(ret)
Python 作業 6
附件里壓縮 了一個目錄(見附件phone.zip),解壓后結構如下。
phone
├─apple
└─samsung
├─note
└─s
這個目錄里面對應了蘋果、三星手機 的價格。
在相應目錄里面,包含對應手機價格的python文件。
請同學們在維持目錄結構不變的前提下,把這個目錄結構做成名為python包。
然后,自己寫一個Python程序調用 那個python包里面的每個
模塊文件(共四個)里面的askPrice 函數,顯示每種手機的價格
同學們先將那個phone包,和自己寫的調用程序文件放在同一個目錄下,
運行調用程序,顯示各種手機價格
同學們再將那個phone包,和自己寫的調用程序文件放在不同的目錄下,
通過設置 sys.path 或者 環境變量PYTHONPATH,
來保證可以找到phone包,並成功調用。
Python 作業 7
下載附件cfiles.zip(見附件cfiles.zip)
解壓該壓縮包,里面 包含了兩個文件。 一個叫 'gbk編碼.txt', 該文件是gbk編碼的。 另一個文件叫 'utf8編碼.txt', 該文件是utf8編碼的。 兩個文件里面的內容都包含中文。 要求大家編寫一個python程序,該程序做到以下2點 1. 將兩個文件內容讀出, 合並內容到一個字符串中, 並能用print語句將合並后的內容正確顯示 2. 然后,程序用中文提示用戶“請輸入 新文件的名稱”, 用戶輸入文件名可以包含中文 將上面合並后的內容存儲到一個新文件中,以utf8格式編碼。 新文件的文件名就是上面用戶輸入的名字。
# 根據不同的編碼格式,指定參數 with open('cfiles/gbk編碼.txt',encoding='gbk') as f1, \ open('cfiles/utf8編碼.txt',encoding='utf8') as f2: # read后,自動轉化成unicode content1 = f1.read() content2 = f2.read() newContent = content1 + content2 print(newContent) newFile = input('請輸入新文件的名稱:') with open(newFile,'w',encoding='utf8') as f: f.write(newContent)
Python 作業 8
下載附件0008.zip(見附件0008.zip)
解壓該壓縮包,里面 包含了3個文件。 都是數據庫中導出的數據文件,
記錄了松勤的老師和授課信息。
其中
1. teacher.txt 文件中包含了 松勤的老師信息,格式如下: id;user_id;desc;display_idx;realname 42;106;;1;小豬老師 43;107;;2;mandy老師 首行表示 下面數據各字段的含義。 第1列id 表示老師的id號。 第2、3、4 列的含義大家可以先不必了解。 第5列realname 表示 老師的姓名 2. course.txt 文件中包含了 松勤的課程信息,格式如下: id;name;desc;display_idx 32;軟件測試框架課程;;1 33;web測試技術課程;;2 首行表示 下面數據各字段的含義。 第1列id 表示課程的id號 第2列name 表示 課程的名稱 第3、4 列的含義大家可以先不必了解。 3. teacher_course.txt 文件中包含了 松勤老師授課信息,格式如下: teacher_id;course_id 42;32 42;33 首行表示 下面數據各字段的含義 第1列teacher_id 表示老師的id號(對應第一張表的老師id號) 第2列course_id表示 課程的id號(對應第二張表的課程id號)。 要求大家編寫一個python程序,根據這3張表的內容,輸出一個包含老師授課信息的文件。 要求格式為 老師姓名: 課程名,例如 小豬老師 : 軟件測試框架課程 mandy老師 : 軟件測試框架課程 mandy老師 : web測試技術課程 實現過程中,有什么問題,請通過課堂上講解的調試方法,盡量自己發現錯誤原因。
# 先讀取文件創建兩張表(兩個dict),記錄老師的 id:name with open('records/course.txt',encoding='utf8') as f : courses = f.read().splitlines()[1:] with open('records/teacher.txt',encoding='utf8') as f : teachers = f.read().splitlines()[1:] courseDict = {} for course in courses: if not course.strip(): continue parts = course.split(';') courseId = parts[0] courseName = parts[1] courseDict[courseId] = courseName teacherDict = {} for teacher in teachers: if not teacher.strip(): continue parts = teacher.split(';') teacherId = parts[0] teacherName = parts[4] teacherDict[teacherId] = teacherName # 根據老師教學記錄表, 將里面的id替換為 名字 with open('records/teacher_course.txt') as f : teacher_courses = f.read().splitlines()[1:] with open('ret.txt','w',encoding='utf8') as f : for tc in teacher_courses: if not tc.strip(): continue parts = tc.split(';') teacherId = parts[0] courseId = parts[1] if (teacherId not in teacherDict) or (courseId not in courseDict): print(f'skip record {tc}') continue ret = f"{teacherDict[teacherId]:10} : {courseDict[courseId]}" print(ret) f.write(ret+'\n')
Python 作業 9
要求大家用面向對象的設計編寫一個python程序,實現一個文字游戲系統。
動物園里面有10個房間,房間號從1 到 10。 每個房間里面可能是體重200斤的老虎或者體重100斤的羊。 游戲開始后,系統隨機在10個房間中放入老虎或者羊。 然后隨機給出房間號,要求游戲者選擇敲門還是喂食。 如果選擇喂食: 喂老虎應該輸入單詞 meat,喂羊應該輸入單詞 grass 喂對了,體重加10斤。 喂錯了,體重減少10斤 如果選擇敲門: 敲房間的門,里面的動物會叫,老虎叫會顯示 ‘Wow !!’,羊叫會顯示 ‘mie~~’。 動物每叫一次體重減5斤。 游戲者強記每個房間的動物是什么,以便不需要敲門就可以喂正確的食物。 游戲3分鍾結束后,顯示每個房間的動物和它們的體重。 實現過程中,有什么問題,請通過課堂上講解的調試方法,盡量自己發現錯誤原因。
單線程版 from random import randint import time class Tiger(object): classname = 'tiger' def __init__(self,weight=200): self.weight = weight def roar(self): print('wow!!!') self.weight -= 5 def feed(self,food): if food == 'meat': self.weight += 10 print('正確,體重 + 10') else : self.weight -= 10 print('太慘了,體重 - 10') class Sheep: classname = 'sheep' def __init__(self,weight=100): self.weight = weight def roar(self): print('mie~~') self.weight -= 5 def feed(self,food): if food == 'grass': self.weight += 10 print('正確,體重 + 10') else : self.weight -= 10 print('太慘了,體重 - 10') class Room: def __init__(self,num,animal): self.num = num self.animal = animal rooms = [] for no in range(10): if randint(0,1): ani = Tiger(200) else: ani = Sheep(100) room = Room(no,ani) rooms.append(room) startTime = time.time() while True: curTime = time.time() if (curTime - startTime) > 120: print('\n\n ********** 游戲結束 ********** \n\n') for idx, room in enumerate(rooms): print('房間 :%s' % (idx + 1), room.animal.classname, room.animal.weight) break roomno = randint(1, 10) room = rooms[roomno-1] # why -1 ? ch = input('我們來到了房間# %s, 要敲門嗎?[y/n]' % roomno) if ch == 'y': room.animal.roar() food = input('請給房間里面的動物喂食:') room.animal.feed(food.strip())
多線程中文版,以后學過多線程后再看 from random import randint import time,os import threading class Tiger: classname = 'tiger' def __init__(self): self.weight = 200 def roar(self): print('wow!!!') self.weight -= 5 def feed(self,food): if food == 'meat': self.weight += 10 print('正確,體重 + 10') else : self.weight -= 10 print('太慘了,體重 - 10') class Sheep: classname = 'sheep' def __init__(self): self.weight = 100 def roar(self): print('mie~~') self.weight -= 5 def feed(self,food): if food == 'grass': self.weight += 10 print('正確,體重 + 10') else : self.weight -= 10 print('太慘了,體重 - 10') class Room: def __init__(self,num,animal): self.num = num self.animal = animal rooms = [] for no in range(10): if randint(0,1) == 0: ani = Tiger() else: ani = Sheep() room = Room(no+1,ani) rooms.append(room) def count_thread(): # 記錄下游戲開始時間 startTime = time.time() while True: time.sleep(0.1) curTime = time.time() if (curTime - startTime) > 20: break print(u'游戲結束') for room in rooms: print(u'房間%s, 里面是%s,體重%s' % (room.num, room.animal.classname, room.animal.weight)) os._exit(0) t = threading.Thread(target=count_thread) t.start() # 循環做如下事情 while True: # 提示房間號,讓用戶選擇 敲門 還是 喂食 curRoomIdx = randint(0,9) room = rooms[curRoomIdx] print('當前來到房間%s,敲門【q】還是喂食【w】' % room.num) ch = input() # 如果選擇敲門:...... if ch == 'q': room.animal.roar() # 如果選擇喂食:...... elif ch == 'w': print('請輸入食物:') food = input() room.animal.feed(food)
Python 作業 10
獲取統計 遠程Linux主機的 可用內存率。
請大家先安裝 paramiko : 執行pip install paramiko 請大家自行百度搜索,安裝虛擬機管理器 virtualbox 或者 vmvareplayer, 創建 64位 虛擬機, 安裝centos鏡像 cetos6.9 下載地址 : http://mirrors.163.com/centos/6.9/isos/x86_64/CentOS-6.9-x86_64-bin-DVD1.iso Putty 下載地址 : https://the.earth.li/~sgtatham/putty/0.70/w32/putty-0.70-installer.msi 然后編寫一個python程序,代碼文件名為 memory.py , 該代碼文件 計划在遠程Linux機器運行。該程序做如下的事情: 每隔5秒鍾 打開文件 /proc/meminfo,該文件包含了系統內存使用信息,前面數行內容如下 MemTotal: 1920648 kB MemFree: 87788 kB Buffers: 229704 kB Cached: 1180244 kB memory.py 程序要將 memFree 、buffers、cached 的值 相加 (結果是可用內存的數量)。 然后除以 MemTotal的值, 得到可用內存占的百分比(賦值給變量 avaMem)。 將 avaMem 的數值存入 結果文件ret.txt中。 上面的程序一直運行,每隔 5秒鍾 獲取記錄一次 avaMem 對應的時間戳, 格式如下 20170315_12:10:00 77% 20170315_12:10:05 74% 20170315_12:10:10 70% 20170315_12:10:15 72% 再編寫一個python程序,代碼文件名為 auto.py,該程序運行起來做如下工作: 以自己名字的拼音(比如lixia) 在遠程機器建立一個目錄 。如果該目錄已經存在則跳過此步驟 拷貝文件memory.py 到遠程機器該目錄下面, 遠程在Linux主機執行文件 memory.py 過5分鍾后,將遠程文件memory.py執行產生的結果文件ret.txt 內容拷貝回本機
memory.py # coding=utf8 import time # MemTotal: 1920648 kB # MemFree: 87788 kB # Buffers: 229704 kB # Cached: 1180244 kB def getContent(lines,field): for line in lines: if field in line: value = line.split(':')[1].split('kB')[0].strip() return int(value) # count 用來時間上計數,防止一直運行 count = 0 while True: count += 1 with open('/proc/meminfo') as f: beginlines = f.readlines()[:8] memTotal = getContent(beginlines,'MemTotal') memFree = getContent(beginlines,'MemFree') buffers = getContent(beginlines,'Buffers') cached = getContent(beginlines,'Cached') # print memTotal,memFree,buffers,cached # 別忘了 * 100 memUsage = (memFree + buffers + cached) *100.0/memTotal # 搜索時間格式 memUsage = '%s %.2f%%' % (time.strftime('%Y%m%d_%H:%M:%S'),memUsage) print(memUsage) with open('ret.txt','a') as f: f.write(memUsage+'\n') time.sleep(5) # 防止一直運行 if count>15: break auto.py # coding=utf8 import paramiko,time ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("120.26.96.231",22,"stt", "stt0707") # 創建自己名字的目錄 dirName = "jcy" # 先檢查 是否已經存在同名目錄了, 如果沒有則創建 stdin, stdout, stderr = ssh.exec_command("ls") # exec_command 返回的是bytes類型,需要解碼 dircontent = stdout.read().decode() print(dircontent) if dirName in dircontent.splitlines(): print('{} already exists'.format(dirName)) else: print('make dir {}'.format(dirName)) ssh.exec_command("mkdir {}".format(dirName)) # 傳輸文件 sftp = ssh.open_sftp() sftp.put('memory.py', '{}/memory.py'.format(dirName)) sftp.close() # 檢查文件是否傳輸成功,可以將檢查文件是否存在機器,做成一個函數。。。 # 執行腳本 # 考慮到長時間沒有消息,網絡連接可能會被斷開。 到網上搜索一番后。 # 設置一個保持連接的參數 transport = ssh.get_transport() transport.set_keepalive(30) print('remote exec python memory.py') ssh.exec_command("cd %s; python memory.py" % dirName) print('wait for 30 seconds...') time.sleep(30) # 傳輸文件 sftp = ssh.open_sftp() sftp.get('{}/ret.txt'.format(dirName),'ret.txt') sftp.close() ssh.close()
Python 作業 11
閱讀下面的兩個知識點
1. ffmpeg可以用下面的參數來錄制Windows 桌面操作的視頻。 ffmpeg.exe -y -rtbufsize 100M -f gdigrab -framerate 10 -draw_mouse 1 -i desktop -c:v libx264 -r 20 -crf 35 -pix_fmt yuv420p -fs 100M "fffffffffffffffff" 其中 fffffffffffffffff 部分 是需要填入 產生的視頻文件名。 錄制過程中,用戶按鍵盤 q 鍵,可以退出錄制。 2. ffmpeg還可以用來合並視頻文件,windows下面的格式如下 ffmpeg.exe -f concat -i concat.txt -codec copy out.mp4 其中concat.txt 是要合並視頻的文件列表。格式如下,每行以file 開頭 后面是要合並的視頻文件名: file 20170330_110818.mp4 file 20170330_110833.mp4 ------------------------------ 下載ffmpeg程序 (進入 http://ffmpeg.zeranoe.com/builds/ 點擊 Download FFmpeg按鈕即可) 要求大家寫一個python程序,運行后提示用戶是要做什么操作,如下 '請選擇您要做的操作:1:錄制視頻,2:合並視頻:' 如果用戶輸入1並回車, 則調用ffmpeg錄制視頻文件,產生在當前目錄下面。 要求錄制的視頻文件名 是當前時間(年月日_時分秒.mp4格式), 比如 '20170330_093612.mp4' (怎么產生這種時間格式的字符串,不知道的請自行網上搜索方法) 如果用戶輸入2並回車,則按字母順序列出當前目錄下所有的 mp4為擴展名 的視頻文件(怎么列出,請自行網上搜索方法),並在前面編上序號。如下所示 --------------------------------- 目錄中有這些視頻文件: 1 - 20170329_202814.mp4 2 - 20170330_093251.mp4 3 - 20170330_093612.mp4 請選擇要合並視頻的視頻文件序號(格式 1,2,3,4) : --------------------------------- 用戶輸入視頻序號(序號以逗號隔開)后, 程序合並視頻文件, 輸出的合並后視頻文件名 固定為 out.mp4
# coding=utf8 import time,os import glob FFMPEG_PATH = 'd:/data/bandicam/tmp/ffmpeg.exe' VIDEO_DIR = 'd:\\' def recording(): # 輸出視頻文件 outputfile = VIDEO_DIR + time.strftime('%Y%m%d_%H%M%S', time.localtime()) + '.mp4' # 工具目錄 settings = '-y -rtbufsize 100M -f gdigrab -framerate 20 ' +\ '-draw_mouse 1 -i desktop -c:v libx264 -r 20 ' +\ '-crf 35 -pix_fmt yuv420p ' \ '-fs 100M "%s"' % outputfile recordingCmdLine = FFMPEG_PATH + ' ' + settings # 查看命令內容 print(recordingCmdLine) # 執行命令錄制視頻 os.system(recordingCmdLine) def merging(): os.chdir(VIDEO_DIR) fileList = glob.glob(VIDEO_DIR + '*.mp4') fileList = [os.path.basename(one) for one in fileList] if fileList: print('\n目錄中有這些視頻文件:') else: print('\n目錄中沒有視頻文件') return idx = 1 for one in fileList: print('%s - %s' % (idx, one)) idx += 1 print('\n請選擇要合並視頻的視頻文件序號(格式 1,2,3,4) :', end=' ') mergeSequence = input('') videoFilesToMer = mergeSequence.split(',') videoFileNamesToMer = [fileList[int(one.strip())-1] for one in videoFilesToMer] print(videoFileNamesToMer) with open('concat.txt','w',encoding='utf8') as f: for one in videoFileNamesToMer: f.write('file ' + one + '\n') cmd = FFMPEG_PATH + ' -f concat -i concat.txt -codec copy out.mp4' # 執行命令錄制視頻 os.system(cmd) while True: print('\n請選擇您要做的操作:1-錄制視頻,2-合並視頻 :', end=' ') choice = input('') if choice == '1': recording() elif choice == '2': merging()
Python 作業 12
先閱讀下面關於Python requests 庫的文章 ,了解 使用它去獲取一個網頁內容的方法。
http://docs.python-requests.org/zh_CN/latest/user/quickstart.html 然后編寫一個python程序,創建兩個子線程,分別到下面的網址獲取文本內容 http://mirrors.163.com/centos/build/rpmcompare5.pl.txt http://mirrors.163.com/centos/6.9/isos/x86_64/README.txt 主線程等待這個兩個子線程獲取到信息后,將其內容合並后存入名為 readme89.TXT 的文件中
# coding=utf8 import requests import threading urls = [ 'http://mirrors.163.com/centos/build/rpmcompare5.pl.txt', 'http://mirrors.163.com/centos/6.9/isos/x86_64/README.txt', ] # 對應urls 依次存儲網頁文件內容, 先創建同樣個數的元素占位 fileContentList = [None for one in urls] # 鎖對象,用來控制訪問 fileContentList lock = threading.Lock() def thread_entry(idx,url): print('thread #%s start' % idx) r = requests.get(url) # 注意上面的代碼不應該放在獲取鎖的代碼中 lock.acquire() # 注意 r.text的類型是unicode,可以在文檔中查到 fileContentList[idx] = r.text lock.release() print('thread #%s end' % idx) if __name__ == '__main__': print('main thread start.') threadpool = [] for idx,url in enumerate(urls): t = threading.Thread(target=thread_entry, args=(idx,url)) t.start() threadpool.append(t) # 等所有 線程結束 for t in threadpool: t.join() # 所有線程結束后,所有內容都獲取到了,合並內容 mergeTxt = '\n\n----------------------\n\n'.join(fileContentList) print(mergeTxt) with open('readme89.txt','w',encoding='utf8') as f: f.write(mergeTxt) print('main thread end.')
Python 作業 13
實現 一個 簡單的 客服聊天系統。
客服中心是tcp服務端程序 客戶使用tcp客戶端程序。
服務端程序 先運行, 綁定本機一個ip地址, 等待客戶端系統連接上來 。
客戶端程序有一個命令行參數, 表示客戶的名字
連接成功后, 客戶端發送給服務端第一個消息 必須告訴客服中心,用戶的名字
一個客戶連接后,別的客戶不能連接, 等到前面的客戶斷開連接后,才能連上。
客戶端和服務端都是手動在終端輸入信息,發送消息后,必須等待接受到對方的消息才能發送下一個消息。
我們定義消息的格式如下:
0008|1|nickname 用豎線隔開3部分的字段,分別表示 消息長度、 消息類型 、消息內容 前面字段是4個字節的字符串,比如'0008',其內容是數字,表示消息的長度, 不足4個字節前面補零。 注意長度是整個消息內容的長度,包括 消息頭部和消息體 后面用豎線隔開的字段,是1個字節的字符串,是消息類型,其內容是數字,1表示客戶昵稱, 2 表示 普通消息 前面兩個字段合起來 0008|1| , 可以看成是一個消息的頭部, nickname 是消息體 再后面用豎線隔開的字段是 消息內容,其長度等於 前面消息長度字段指明的長度 減去 消息頭部長度 (也就是7個字節) 服務端程序在下面, 大家參考服務端程序的實現,開發客戶端程序和服務端進行通訊
# coding=utf8 import sys from socket import socket,AF_INET,SOCK_STREAM HOST = '' PORT = 21567 BUFSIZ = 1024 ADDR = (HOST, PORT) class CloseSocketError(Exception): pass # 一個 ConnectionHandler 處理和一個客戶端的連接 class ConnectionHandler: # 0008|1|nickname LEN_MSG_LEN_FIELD = 4 LEN_MSG_LEN_TYPE_FIELD = 7 def __init__(self,sock): # 消息緩存區 self._readbuffer = b'' self.sock = sock self.customername = '' # msgBody 是 unicode @staticmethod def encode(msgType,msgBody): rawMsgBody = msgBody.encode('utf8') msgLenth = '{:04}' \ .format(len(rawMsgBody)+ConnectionHandler.LEN_MSG_LEN_TYPE_FIELD) \ .encode() msgType = f'{msgType}'.encode() return b'|'.join([msgLenth,msgType,rawMsgBody]) @staticmethod def decode(rawmsg): msgType = int(rawmsg[5:6]) # 這樣寫rawmsg[5] 返回的是字節對應的數字 msgbody = rawmsg[ConnectionHandler.LEN_MSG_LEN_TYPE_FIELD:].decode('utf8') return [msgType,msgbody] def readMsg(self): bytes = self.sock.recv(BUFSIZ) # ** 用不同的返回值表示不同的含義 # 當對方關閉連接的時候,拋出異常 if not bytes: self.sock.close() raise CloseSocketError() # 應用程序的讀取緩沖,和前面講的系統的讀取緩沖是兩個不同的緩沖 self._readbuffer += bytes buffLen = len(self._readbuffer) # 如果已經獲取了消息頭部 (包括 消息長度,消息類型) if buffLen >= self.LEN_MSG_LEN_TYPE_FIELD: msgLen = int(self._readbuffer[:self.LEN_MSG_LEN_FIELD]) # 緩存區消息 已經包含了一個整體的消息(包括 消息長度,消息類型,消息體) if buffLen >= msgLen: # 從緩存區,截取整個消息 msg = self._readbuffer[0:msgLen] # 緩存區變成剩余的消息部分 self._readbuffer = self._readbuffer[msgLen:] return self.decode(msg) # 如果已經獲取的消息還不包括一個完整的消息頭部, 不做處理等待下面繼續接受消息 else: return None print('get:%s' % bytes) # msgBody 是 unicode def sendMsg(self,msgType,msgBody): self.sock.sendall(self.encode(msgType,msgBody)) def handleMsg(self,msgType,msgBody): # 客戶名稱 if msgType == 1: self.customername = msgBody print('客戶名稱設置:%s' % self.customername) # 普通消息 elif msgType == 2: print(msgBody) print('---------------') # 客服輸入消息內容 msgSend = input('>>') self.sendMsg(2,msgSend) # 主循環,不斷的接受消息發送消息 def mainloop(self): while True: try: msg = self.readMsg() # msg 里面包含了 type 和body if msg: msgType,msgBody= msg self.handleMsg(msgType,msgBody) except CloseSocketError: print('對方斷開了連接,等待下一個客戶') break except IOError: print('對方斷開了連接,等待下一個客戶') break #創建socket,指明協議 tcpSerSock = socket(AF_INET, SOCK_STREAM) #綁定地址和端口 tcpSerSock.bind(ADDR) tcpSerSock.listen(5) print('等待客戶端連接...') while True: #阻塞式等待連接請求 tcpCliSock, addr = tcpSerSock.accept() print('有客戶連接上來', addr) handler = ConnectionHandler(tcpCliSock) handler.mainloop() tcpSerSock.close()
# coding=utf-8 from socket import * import traceback,sys HOST = 'localhost' PORT = 21567 BUFSIZ = 1024 ADDR = (HOST, PORT) class CloseSocketError(Exception): pass class ConnectionHandler: # 0008|1|nickname LEN_MSG_LEN_FIELD = 4 LEN_MSG_LEN_TYPE_FIELD = 7 def __init__(self,sock): # 消息緩存區 self._readbuffer = b'' self.sock = sock self.customername = '' # msgBody 是 unicode @staticmethod def encode(msgType,msgBody): rawMsgBody = msgBody.encode('utf8') msgLenth = '{:04}' \ .format(len(rawMsgBody)+ConnectionHandler.LEN_MSG_LEN_TYPE_FIELD) \ .encode() msgType = f'{msgType}'.encode() return b'|'.join([msgLenth,msgType,rawMsgBody]) @staticmethod def decode(rawmsg): msgType = int(rawmsg[5:6]) msgbody = rawmsg[ConnectionHandler.LEN_MSG_LEN_TYPE_FIELD:].decode('utf8') return [msgType,msgbody] def readMsg(self): bytes = self.sock.recv(BUFSIZ) # ** 用不同的返回值表示不同的含義 # 當對方關閉連接的時候,拋出異常 if not bytes: self.sock.close() raise CloseSocketError() self._readbuffer += bytes buffLen = len(self._readbuffer) # 如果已經獲取了消息頭部 (包括 消息長度,消息類型) if buffLen >= self.LEN_MSG_LEN_TYPE_FIELD: msgLen = int(self._readbuffer[:self.LEN_MSG_LEN_FIELD]) # 緩存區消息 已經包含了一個整體的消息(包括 消息長度,消息類型,消息體) if buffLen >= msgLen: # 從緩存區,截取整個消息 msg = self._readbuffer[0:msgLen] # 緩存區變成剩余的消息部分 self._readbuffer = self._readbuffer[msgLen:] return self.decode(msg) # 如果已經獲取的消息還不包括一個完整的消息頭部, 不做處理等待下面繼續接受消息 else: return None print('--> %s' % bytes) # msgBody 是 unicode def sendMsg(self,msgType,msgBody): self.sock.sendall(self.encode(msgType,msgBody)) def handleMsg(self,msgType,msgBody): # 客戶名稱 if msgType == 2: print(msgBody) print('---------------') def userinputAndSend(self): msgSend = input('>>') self.sendMsg(2, msgSend) # 主循環,不斷的接受消息發送消息 def mainloop(self): # 先發送客戶名稱 userName = '***' if len(sys.argv) > 1: userName = sys.argv[1].decode(sys.stdin.encoding) self.sendMsg(1,userName) while True: try: self.userinputAndSend() # print('reading...') msg = self.readMsg() if msg: msgType,msgBody= msg self.handleMsg(msgType,msgBody) except CloseSocketError: print('對方斷開了連接,程序退出') return except IOError: print('對方斷開了連接,程序退出') return #創建socket,指明協議 tcpCliSock = socket(AF_INET, SOCK_STREAM) #連接遠程地址和端口 tcpCliSock.connect(ADDR) handler = ConnectionHandler(tcpCliSock) handler.mainloop()
Python 作業 14
有的時候,工作中,我們需要存檔文件, 會拷貝一個目錄里面所有的文件到另外的機器上
如果是特別機密的存檔文件,比如合約,財務信息等,我們不希望這些目錄中的文件有任何修改。
假如有員工偷偷修改了存檔的文件,就會和源文件不一致
我們需要實現一個工具,能夠快速檢測存檔目錄中的文件和源文件是否有不同。
方法是,為源目錄中的所有文件產生一個校驗文件,里面記錄了所有文件的校驗和(使用MD5算法)
這樣存檔后,如果有人修改任何一個文件,
運行工具 檢查 就能發現 現有文件的校驗和 與源文件中的校驗文件里面記錄的值 不同
網上有類似的工具: filecheckmd5.exe 下載地址:https://github.com/jcyrss/songqin-testdev/raw/master/others/softwares/filecheckmd5.zip 要求大家用Python語言開發類似的工具。 實現難點 如下,大家自己到網上搜索解決方法,鍛煉自己查詢資料,解決問題的能力, 難點1: 圖形界面 大家可以使用Python 內置的圖形界面庫 tkinter 去實現 難點2: md5校驗和的概念 和 生成文件md5校驗和的方法 (特別是對大文件的支持)
from tkinter import Button, Tk, HORIZONTAL,Label,filedialog,messagebox,END from tkinter.ttk import Notebook,Frame from tkinter.scrolledtext import ScrolledText import time,os,threading,hashlib MD5_VALIDATION_FILE = u'FCMD5-sums.MD5' def center(toplevel): toplevel.update_idletasks() w = toplevel.winfo_screenwidth() h = toplevel.winfo_screenheight() size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x')) x = w/2 - size[0]/2 y = h/2 - size[1]/2 toplevel.geometry("%dx%d+%d+%d" % (size + (x, y))) def generate_file_md5( filepath, blocksize=2**20): m = hashlib.md5() with open( filepath, "rb" ) as f: while True: buf = f.read(blocksize) if not buf: break m.update( buf ) return m.hexdigest() class MonApp(Tk): def __init__(self): super().__init__() self.minsize(width=650, height=550) center(self) self.srcFolderPath = '' self.targetFolderPath = '' self.title(u'md5校驗器') self.tabMgr = Notebook(self) self.tab1Initial() self.tab2Initial() def tab1Initial(self): tab1 = Frame(self.tabMgr) self.tabMgr.add(tab1, text=u' 創建校驗碼 ') self.tabMgr.pack(expand=1, fill="both") # tab1.rowconfigure(1, minsize=100) # tab1.columnconfigure(0,minsize=100) Button(tab1, text=u'選擇源文件夾', command=self.selectSrcFolder).grid(row=0, column=0, columnspan=3, padx=20, pady=20) self.txtSrcFolder = Label(tab1, text= " ") self.txtSrcFolder.grid(row=1, column=0, columnspan=3, ) self.btnCreating = Button(tab1, text='Go!', command=self.createMD5) self.btnCreating.grid(row=2, column=0, columnspan=2, padx=20, pady=10) self.txtCreating = ScrolledText(tab1) self.txtCreating.grid(row=3, column=0, rowspan=2,columnspan=2, padx=20, pady=10) # self.txtCreating['state']= 'disabled' def tab2Initial(self): tab2 = Frame(self.tabMgr) self.tabMgr.add(tab2, text=u' 進行校驗 ') self.tabMgr.pack(expand=1, fill="both") Button(tab2, text=u'選擇目標文件', command=self.selectTargetFolder).grid(row=0, column=0, columnspan=3, padx=20, pady=20) self.txtTargetFile = Label(tab2, text= " ") self.txtTargetFile.grid(row=1, column=0, columnspan=3, ) self.btnValidating = Button(tab2, text=u'校驗!', command=self.validateMD5) self.btnValidating.grid(row=2, column=0, columnspan=2, padx=20, pady=10) self.txtValidating = ScrolledText(tab2) self.txtValidating.grid(row=3, column=0, rowspan=2,columnspan=2, padx=20, pady=10) def selectSrcFolder(self): self.srcFolderPath = os.path.abspath(filedialog.askdirectory()) self.txtSrcFolder['text'] = self.srcFolderPath # self.targetFolderPath = filedialog.askdirectory() # self.txtTargetFile['text'] = self.targetfilePath def selectTargetFolder(self): self.targetFilePath = os.path.abspath(filedialog.askopenfilename(defaultextension='.MD5', filetypes=[('MD5 file','*.MD5'),('All files','*.*')])) self.targetFolderPath = os.path.dirname(self.targetFilePath) self.txtTargetFile['text'] = self.targetFilePath def _getAllFiles(self,directory): fileList = [] for path, dirs, files in os.walk(os.path.abspath(directory)): # 去掉 System Volume Information 卷信息文件 if 'System Volume Information' in path: continue for filename in files: # 去掉校驗文件本身 if filename == MD5_VALIDATION_FILE: continue filepath = os.path.join(path, filename) # print(filepath) fileList.append(filepath) return fileList def createMD5(self): if not self.srcFolderPath.strip(): messagebox.showwarning(u'錯誤', u'請先選擇目錄') return def real_create(): allfiles = self._getAllFiles(self.srcFolderPath) self.txtCreating.delete(1.0, END) self.btnCreating['state'] = 'disabled' allfileMd5 = [] for one in allfiles: basedir = self.srcFolderPath if not basedir.endswith('\\'): basedir += '\\' curFile = one.replace(basedir, '') self.txtCreating.insert(END, curFile + '\n') md5Record = '%s|%s' % (generate_file_md5(one), curFile) allfileMd5.append(md5Record) self.txtCreating.see("end") with open(os.path.join(self.srcFolderPath, MD5_VALIDATION_FILE), 'w',encoding='utf8') as md5file: md5file.write('\n'.join(allfileMd5)) messagebox.showinfo('OK', u'處理完成') self.btnCreating['state'] = 'normal' threading.Thread(target=real_create).start() def validateMD5(self): if not self.targetFolderPath.strip(): messagebox.showwarning(u'錯誤', u'請先選擇目錄') return if not os.path.isfile(self.targetFilePath): messagebox.showwarning(u'錯誤', u'沒有校驗記錄文件:'+self.targetFilePath) return def real_check(): # 讀取md5校驗文件 md5Table = {} with open(self.targetFilePath,'r',encoding='utf8') as md5file: for line in md5file.read().splitlines(): line = line.strip() if line.startswith(';'): continue if line.count('|') != 1: continue md5str,filename = line.split('|') md5Table[filename] = md5str if len(md5Table) == 0: messagebox.showwarning('warning',u'文件中沒有md5記錄信息') return allfiles = self._getAllFiles(self.targetFolderPath) self.txtValidating.delete(1.0, END) self.btnValidating['state']= 'disabled' errList = '' for one in allfiles: basedir = self.targetFolderPath if not basedir.endswith('\\'): basedir += '\\' curFile = one.replace(basedir,'') self.txtValidating.insert(END, curFile+' ... ') self.txtValidating.see("end") if curFile not in md5Table: self.txtValidating.insert(END, u'md5校驗記錄不存在!!!!!!!!!!!!\n') errList += curFile + u' md5校驗記錄不存在\n' continue md5Str_ori = md5Table[curFile] md5Str_now = generate_file_md5(one) if md5Str_now != md5Str_ori: self.txtValidating.insert(END, u'md5校驗不匹配!!!!!!!!!!!!!!\n') errList += curFile + u' md5校驗不匹配\n' continue self.txtValidating.insert(END, u'ok\n') for one in md5Table.keys(): if os.path.join(self.targetFolderPath, one) not in allfiles: err = u'{} 文件丟失!!!!!!!!!!!!!\n'.format(one) errList += err self.txtValidating.insert(END, u'\n\n============ 校驗結果 =========== \n\n') if errList: info = u'校驗結果有錯誤!!!' self.txtValidating.insert(END, errList) else: info = u'校驗結果完全匹配' self.txtValidating.insert(END, u' ********* 通過 *********') self.txtValidating.see("end") messagebox.showinfo('OK',u'處理完畢 , ' + info) self.btnValidating['state']= 'normal' threading.Thread(target=real_check).start() if __name__ == '__main__': app = MonApp() app.mainloop()
pyhton實現斐波納契數列前20項
lis = [] for i in range(20): if i == 0 or i==1: lis.append(1) else: lis.append(lis[i-2] + lis[i-1]) print(lis)
python實現n!
def jicheng(n): if n == 0 or n == 1: return 1 else: return (n*jicheng(n-1)) if __name__ == "__main__": print(jicheng(4))
python實現階乘遞歸之和1!+2!+3!+。。。+20!
def jicheng(n): if n == 1: return 1 else: return n*jicheng(n-1) print("將結果寫入列表之后求和".center(80,'*')) lis = [] for i in range(1,21): lis.append(jicheng(i)) print(sum(lis)) print("for循環直接調用遞歸函數求和".center(80,'*')) sum_0 = 0 for i in range(1,21): sum_0 +=jicheng(i) print(sum_0)