Python 读取\u csv获取发生异常的行
我试图用pandas分析的HTTP日志文件有时会出现意外的行。以下是我加载数据的方式:Python 读取\u csv获取发生异常的行,python,pandas,exception,Python,Pandas,Exception,我试图用pandas分析的HTTP日志文件有时会出现意外的行。以下是我加载数据的方式: df = pd.read_csv('mylog.log', sep=r'\s(?=(?:[^"]*"[^"]*")*[^"]*$)(?![^\[]*\])', engine='python', na_values=['-'], header=None, usecols=[0, 3, 4, 5, 6, 7, 8,10],
df = pd.read_csv('mylog.log',
sep=r'\s(?=(?:[^"]*"[^"]*")*[^"]*$)(?![^\[]*\])',
engine='python', na_values=['-'], header=None,
usecols=[0, 3, 4, 5, 6, 7, 8,10],
names=['ip', 'time', 'request', 'status', 'size',
'referer','user_agent','req_time'],
converters={'status': int, 'size': int, 'req_time': int})
它适用于我拥有的大多数日志(来自同一台服务器)。但是,在加载某些日志时,会引发异常:
或者
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'
或
在本例中,以下是触发第二个异常的行:
22.111.117.229, 22.111.117.229 - - [19/Sep/2018:22:17:40 +0200] "GET /agent/10577/bdl HTTP/1.1" 204 - "-" "okhttp/3.8.0" apibackend.site.fr 429282
为了找到犯罪行的编号,我使用了以下(非常慢)函数:
def search_error_dichotomy(path):
borne_inf = 0
log = open(path)
borne_sup = len(log.readlines())
log.close()
while borne_sup - borne_inf>1:
exceded = False
search_index = (borne_inf + borne_sup) // 2
try:
pd.read_csv(path,...,...,nrows=search_index)
except:
exceded = True
if exceded:
borne_sup = search_index
else:
borne_inf = search_index
return search_index
我想要的是这样的:
try:
pd.read_csv(..........................)
except MyError as e:
print(e.row_number)
其中e.row_number是混乱行的编号
先谢谢你
解决方案
所有的功劳都归功于devssh,他的建议不仅加快了流程,而且让我能够一次获得所有意想不到的线路。以下是我所做的:
df = pd.read_csv(path,
sep=r'\s(?=(?:[^"]*"[^"]*")*[^"]*$)(?![^\[]*\])',
engine='python', na_values=['-'], header=None,
usecols=[0, 3, 4, 5, 6, 7, 8,10],
names=['ip', 'time', 'request', 'status', 'size',
'referer', 'user_agent', 'req_time'])
wrong_lines = {}
def convert_int_feedback_index(row,col):
try:
ans = int(row[col])
except:
wrong_lines[row['index']] = row[col]
ans = pd.np.nan
return ans
您是否尝试过
pd.read_csv(…,nrows=10)
查看它是否能在10行上运行
也许您不应该使用转换器
来指定数据类型
加载数据帧,然后将数据类型应用于列,如
df[“column”]=df[“column”]。astype(np.int64)
或自定义函数,如df[“column”]=df[“column”]。应用(lambda x:convert_type(x))
并在函数convert_type中自行处理错误。最后,通过调用
df.to_csv(“preprocessed.csv”,headers=True,index=False)更新csv
我认为您无法从pd.read\u csv本身获取行号。分隔符本身看起来太复杂了 或者您可以尝试将csv作为单列数据帧读取,然后使用
df[“column”].str.extract
使用正则表达式提取列。这样,您可以控制如何引发异常或处理错误的默认值
df.reset_index()
将把行号作为列提供给您。这样,如果您选择,您也将获得行号。它将为您提供带有行号的索引列。将其与“应用于多个列”相结合,您可以自定义所有内容。有什么例外?@devssh:是的,我尝试了小nrow,错误出现在第271119行。至于删除转换器并使用.astype或.apply,这听起来是个好主意,但我不知道如何检索发生异常的行的编号。你看到我的建议了吗?它将为您提供带有行号的索引
列。将其与多个列上的应用相结合,您可以自定义所有内容。使用这种替代方法,您现在似乎可以默认获得行号了,对吗?@devssh:Wow,使用“df.reset_index()”确实可以做到这一点!非常感谢你!
df = df.reset_index()
wrong_lines = {}
def convert_int_feedback_index(row,col):
try:
ans = int(row[col])
except:
wrong_lines[row['index']] = row[col]
ans = pd.np.nan
return ans
df[col] = df.apply(convert_int_feedback_index, axis=1, col=col)