Python生成器读取/etc/passwd返回空行,求问题排查与解决
问题
我正在学习Python,尝试读取Linux系统下的/etc/passwd文件,想实现跳过空行的逻辑,而且知道readline()适合处理大文件。我写的代码如下:
import pandas as pd import numpy as np def nonblank_lines(f): rawline=f.readline() while rawline != '': line=rawline.rstrip() print("#'#'#'#'#'",line) if line: yield line rawline=f.readline() filein="/etc/passwd" datain=[] columnnames=['Username','Password','UID','GID','Name of User','HOMEDIR','Login Shell'] with open(filein,'r') as passwdline: print(f"passwdline: {passwdline}") for line in nonblank_lines(passwdline): print(f"Back from function ====, {line}") datain.append(line.split(':'))
为测试程序,我特意在/etc/passwd中添加了空行,内容如下:
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync
但程序持续输出空行,结果如下:
#'#'#'#'#' #'#'#'#'#' #'#'#'#'#' #'#'#'#'#' #'#'#'#'#'
我猜测问题出在yield语句后的readline(),但不清楚原因,请问我哪里出错了?
问题分析与解决
你的问题确实出在readline()的调用位置上:在nonblank_lines函数里,只有当遇到有效非空行时才会执行rawline=f.readline(),一旦碰到空行,这个读取下一行的操作就不会触发,导致循环一直卡在当前的空行上,反复输出空内容。
修正方案
把rawline=f.readline()移到while循环的末尾,不管当前行是否有效,都读取下一行,这样就能正常遍历整个文件了:
def nonblank_lines(f): rawline = f.readline() while rawline != '': line = rawline.rstrip() print("#'#'#'#'#'", line) if line: yield line # 无论当前行是否为空,都读取下一行 rawline = f.readline()
更简洁的写法
其实可以利用Python文件对象本身就是可迭代对象的特性,简化生成器函数,不用手动调用readline(),代码可读性更高,同时依然保持逐行读取的特性(适合大文件):
def nonblank_lines(f): for line in f: stripped_line = line.rstrip() print("#'#'#'#'#'", stripped_line) if stripped_line: yield stripped_line
这种写法会自动逐行遍历文件,遇到空行时直接跳过yield,遇到有效行就返回,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

