希望那出題狗?能看到,面試題沒必要這麼HY coder吧
-
題目:
```sql CREATE TABLE `student` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(250) DEFAULT '1' COMMENT '名字', `teacher_id` int(11) DEFAULT '0' COMMENT '老師id' ) ENGINE=InnoDB CHARSET=utf8 COMMENT='學生表'; CREATE TABLE `teacher` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(250) DEFAULT '1' COMMENT '名字', `check_time` datetime NOT NULL COMMENT '打卡時間' ) ENGINE=InnoDB CHARSET=utf8 COMMENT='老師表' ``` 用python語言, 寫一個"老師"進程, 要求: 1. 進程啓動時, 會往teacher表裏面插入一條記錄, 記下這條記錄的id值, 保存爲t_id. 2. 進程定期更新其t_id對應記錄的"check_time"字段. 3. 進程定期掃描student表, 如果有teacher_id爲0的記錄, 將該字段更新爲其t_id. 4. 當啓動兩個進程A和B時, 這兩個進程可以平分所有的student, 即一半student的teacher_id爲進程A的t_id, 另一半student的teacher_id爲進程B的t_id. 5. 再啓動一個進程C的時候, 1/3的student的teacher_id爲進程A的t_id, 1/3爲歸進程B, 1/3歸進程C. 6. 當進程A因爲各種原因掛了, 不再更新check_time字段時, 進程B和進程C可以瓜分進程A託管的學生.
-
我寫的答案:
import multiprocessing from pymysql import * import datetime import threading import time import os class MyMysql(object): """ 進程類 """ def __init__(self): self.row_range = "" # 掃面的工作範圍元組類型 self.con = connect( host='localhost', port=3306, database='ceshi', user='root', password='mysql', charset='utf8') self.cs = self.con.cursor() self.time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.t_id = "" self.q = "" # todo 這裏留一個通訊隊列 self.q1 = "" # 線程運行數量隊列 def mysql_init(self): """ # 1. 進程啓動時, 會往teacher表裏面插入一條記錄, 記下這條記錄的id值, 保存爲t_id. :return: 返回值是t_id """ self.cs.execute("""insert into teacher(check_time) \ values(str_to_date(\'%s\','%%Y-%%m-%%d %%H:%%i:%%s'));""" % self.time) self.cs.execute("""SELECT LAST_INSERT_ID()""") self.t_id = self.cs.fetchone()[0] def update_teacher(self): """ # 2. 進程定期更新其t_id對應記錄的"check_time"字段. --實現 :return: """ while True: print("update ok") time.sleep(3) self.time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") self.cs.execute("""update teacher set \ check_time=str_to_date(\'%s\','%%Y-%%m-%%d %%H:%%i:%%s') where id=%d;""" % (self.time, self.t_id)) self.con.commit() def up_stu_tid(self): """ # 3. 進程定期掃描student表, 如果有teacher_id爲0的記錄, 將該字段更新爲其t_id. # 4. 當啓動兩個進程A和B時, 這兩個進程可以平分所有的student, 即一半student的teacher_id爲進程A的t_id, # 另一半student的teacher_id爲進程B的t_id。 # 5. 再啓動一個進程C的時候, 1/3的student的teacher_id爲進程A的t_id, 1/3爲歸進程B, 1/3歸進程C. :return: """ while True: time.sleep(5) self.cs.execute( """select id from student where teacher_id=0 limit %d,%d;""" % self.row_range) a = self.cs.fetchall() for i in a: self.cs.execute( """update student set teacher_id=%s where id= %s""" % (self.t_id, i[0])) def tell_mian_live(self): """ 告訴主進程我還活着 和 進程 id 此函數要定期執行 :return: """ time.sleep(1) # 每兩秒執行一次,進行函數的使用 self.q.put(os.getpid()) # 將子進程號放到隊列中 def get_p_live(self): """ 更改全局變量 :return: """ while True: try: self.row_range = self.q1.get() except Exception as e: print(e) def my_pro_run(self, range_r, q, q1): """ 總的運行程序 :return: """ self.q = q # 重置進程隊列 self.q1 = q1 self.row_range = range_r print(self.row_range) self.mysql_init() print(self.t_id, type(self.t_id)) # todo 開啓定時報告存活 功能 threading.Thread(target=self.tell_mian_live).start() threading.Thread(target=self.update_teacher).start() threading.Thread(target=self.up_stu_tid).start() self.con.commit() class JinCheng(object): def __init__(self, fun, num): self.conn = connect( host='localhost', port=3306, database='ceshi', user='root', password='mysql', charset='utf8') self.cs2 = self.conn.cursor() self.cs2.execute("select count(*) from teacher;") self.mysql_row = self.cs2.fetchall()[0][0] # 數據中的行數 self.pro_list = [fun] * num self.pro_arg = "" self.q = multiprocessing.Queue() # todo 進程通訊工具 self.q1 = multiprocessing.Queue() # todo 進程通訊工具 self.chang_num_pro = 0 def start_pro(self): for i in self.pro_list: time.sleep(0.02) # 延遲0.02 秒 生成文件 multiprocessing.Process(target=i, args=( (self.pro_arg[0][len(self.pro_list) - 1], self.pro_arg[1]), self.q, self.q1) ).start() print(" 開啓成功") def cha_xu(self, a, b): """ :param a: 數據庫行數 :param b: 進程數 :return: 步進值和點值 -》 第幾個進程 號-1 加步長 """ step_int = a // len(self.pro_list) if step_int % 2 == 0: step = round(a / b) + 1 else: step = round(a / b) limit_page = [] for i in range(0, a, step): limit_page.append(i) self.pro_arg = (limit_page, step) print(self.pro_arg) def check_pro(self): """ 判斷開啓的進程和進程列表中的數量是不是相同 此函數單獨開工線程使用 :return: """ start_pro = len(self.pro_list) print("start_pro", start_pro) def q_getpid(start_pro): get_q = [] # 進程號列表 for i in range(start_pro): try: count = self.q.get() if count in get_q: pass else: get_q.append(count) except Exception as e: print(e) return get_q while True: a = q_getpid(start_pro) b = q_getpid(start_pro) if a == b: pass else: for i in a: if i in b: pass else: print("死掉的進程", i) start_pro -= 1 # 進程數減少1 self.chang_num_pro = start_pro self.cha_xu(self.mysql_row, self.chang_num_pro) self.q1.put(self.pro_arg) # 將更改後的參數發送給子進程 def run_pro(self): """ 運行初始化 :return: """ self.cha_xu(self.mysql_row, len(self.pro_list)) self.start_pro() threading.Thread(target=self.check_pro).start() if __name__ == '__main__': a = MyMysql() jin = JinCheng(a.my_pro_run, 3) jin.run_pro()
-
微信