Python人脸识别考勤系统遇TypeError: can only join an iterable 如何解决?
问题描述
我正在使用Python开发一款人脸识别考勤程序,运行程序时终端报错TypeError: can only join an iterable,错误出现在代码行n="+".join(n)处。若注释该行代码,CV捕获窗口中的Course、Semester、Roll No、Name字段仅显示None。
相关代码:
def mark_attendance(self,i,r,n,name): with open("attendance.csv","r+",newline="\n") as f: myDatalist=f.readlines() name_list=[] for line in myDatalist: entry=line.split((",")) name_list.append(entry[0]) if((name not in name_list) and (i not in name_list)): now=datetime.now() d1=now.strftime("%Y/%m/%d") dtString=now.strftime("%H:%M:%S") f.writelines(f"{n}, {r}, {i}, {name}, {dtString}, {d1}, Present\n") #================face recognition================== def face_recog(self): def draw_boundray(img,classifier,scaleFactor,minNeighbors,color,text,clf): gray_image=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) features=classifier.detectMultiScale(gray_image,scaleFactor,minNeighbors) coord=[] for (x,y,w,h) in features: cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3) id,predict=clf.predict(gray_image[y:y+h,x:x+w]) confidence=int((100*(1-predict/300))) conn = mysql.connector.connect(username='root', password='',host='localhost',database='face_recognition',port=3306) cursor = conn.cursor() cursor.execute("select Course from student where Roll_No="+str(id)) n=cursor.fetchone() n="+".join(n) cursor.execute("select Semester from student where Roll_No="+str(id)) r=cursor.fetchone() r="+".join(r) cursor.execute("select Roll_No from student where Roll_No="+str(id)) i=cursor.fetchone() i="+".join(i) cursor.execute("select Name from student where Roll_No="+str(id)) name=cursor.fetchone() name="+".join(name) if confidence > 77: cv2.putText(img,f"Course: {n}",(x,y-105),cv2.FONT_HERSHEY_COMPLEX,0.8,(64,15,223),2) cv2.putText(img,f"Semester: {r}",(x,y-80),cv2.FONT_HERSHEY_COMPLEX,0.8,(64,15,223),2) cv2.putText(img,f"Roll No: {i}",(x,y-55),cv2.FONT_HERSHEY_COMPLEX,0.8,(64,15,223),2) cv2.putText(img,f"Name: {name}",(x,y-30),cv2.FONT_HERSHEY_COMPLEX,0.8,(64,15,223),2) self.mark_attendance(i,r,n,name) else: cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,255),3) cv2.putText(img,"Not Found",(x,y-5),cv2.FONT_HERSHEY_COMPLEX,0.8,(255,255,0),3) coord=[x,y,w,y] return coord #========== def recognize(img,clf,faceCascade): coord=draw_boundray(img,faceCascade,1.1,10,(255,25,255),"Face",clf) return img faceCascade=cv2.CascadeClassifier("haarcascade_frontalface_default.xml") clf=cv2.face.LBPHFaceRecognizer_create() clf.read("clf.xml") videoCap=cv2.VideoCapture(0) while True: ret,img=videoCap.read() img=recognize(img,clf,faceCascade) cv2.imshow("Face Detector",img) if cv2.waitKey(1) == 27: break videoCap.release() cv2.destroyAllWindows()
终端错误信息:
Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\Khursaid\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1885, in __call__ return self.func(*args) File "E:\Final Project\New FAS\login.py", line 417, in face_recog img=recognize(img,clf,faceCascade) File "E:\Final Project\New FAS\login.py", line 406, in recognize coord=draw_boundray(img,faceCascade,1.1,10,(255,25,255),"Face",clf) File "E:\Final Project\New FAS\login.py", line 374, in draw_boundray n="+".join(n) TypeError: can only join an iterable
解决方案
问题根源
- 当数据库中没有匹配当前
Roll_No的记录时,cursor.fetchone()返回None,此时调用"+".join(None)会触发TypeError,因为None不是可迭代对象。 - 即使有匹配记录,
fetchone()返回的是单元素元组(例如("计算机科学",)),用join完全没必要,直接提取元组内的元素即可。
修改步骤
- 先判断
fetchone()的返回值是否为None,避免空值报错; - 直接提取元组中的第一个元素,替代不必要的
join操作; - 改用参数化查询,避免SQL注入风险。
修改后的数据库查询代码:
# 建立数据库连接(建议提到函数外部,避免重复创建连接) conn = mysql.connector.connect(username='root', password='',host='localhost',database='face_recognition',port=3306) cursor = conn.cursor() # 查询Course cursor.execute("select Course from student where Roll_No=%s", (id,)) n = cursor.fetchone() n = n[0] if n else "Unknown" # 查询Semester cursor.execute("select Semester from student where Roll_No=%s", (id,)) r = cursor.fetchone() r = r[0] if r else "Unknown" # 查询Roll_No cursor.execute("select Roll_No from student where Roll_No=%s", (id,)) i = cursor.fetchone() i = str(i[0]) if i else "Unknown" # 查询Name cursor.execute("select Name from student where Roll_No=%s", (id,)) name = cursor.fetchone() name = name[0] if name else "Unknown"
额外优化建议
- 减少数据库连接次数:当前代码每次人脸检测循环都创建新的数据库连接,会大幅降低性能,建议将连接放在
draw_boundray函数外部,或者使用数据库连接池。 - 优化考勤判断逻辑:
mark_attendance函数中if((name not in name_list) and (i not in name_list))存在逻辑问题,应仅通过学号(Roll_No)判断是否已考勤,因为姓名可能存在重复。
内容的提问来源于stack exchange,提问作者Khursaid Ansari
相关产品推荐
相关产品推荐

