如何在不使用CSV导入的情况下在python中编写自定义CSV阅读器



我正试图解决pyschools网站上的一个问题,该问题要求编写一个脚本,以逗号"作为分隔符读取CSV文件并返回记录列表。当在他们的网站上运行我的脚本时,它使用以下测试用例返回为不正确:csvReader('books.cv'([0]因此返回:

['"Pete,Zelle","Intro to HTML, CSS",2011']

当预期结果为:时

['Pete,Zelle', 'Intro to HTML, CSS', '2011']

我注意到这个问题与引号"&'有关,但仍然没有找到正确的答案,对行变量使用替换(","(来删除双引号并不能解决问题,因为它返回为:

['Pete,Zelle,Intro to HTML, CSS,2011']

其中它删除了一些单词的最后一个引号,例如Zelle,而不是Zelle’,。

下面将提供练习、问题和我当前脚本的链接。非常感谢您的任何解释或帮助。

链接:http://www.pyschools.com/quiz/view_question/s13-q8

问题:编写一个函数来读取以","作为分隔符的CSV文件,并返回记录列表。函数必须能够忽略位于一对双引号"内的"。

脚本:

def csvReader(filename):
records = []
for line in open(filename):
line = line.rstrip()  # strip 'n'
if line=='","':
continue           # ignore empty line
records.append([line.replace('"','')])

return records

我在寻找您要读取的CSV文件。听起来好像你需要分开字段,同时忽略引号之间的任何分隔符。

在这种情况下,我建议使用CSV库并设置引号。

import csv
record = '"Pete,Zelle","Intro to HTML, CSS",2011'
newStr = [ '"{}"'.format(x) for x in list(csv.reader([record], delimiter=',', quotechar='"'))[0] ]
print(newStr)

将返回["Pete,Zelle"','"HTML简介,CSS"',"2011"']

在您的功能中,您可以将其合并为以下

import csv
def csvReader(filename):
records = []
for line in open(filename):
line = line.rstrip()  # strip 'n'
if line=='","':
continue           # ignore empty line
newLine = [ '"{}"'.format(x) for x in list(csv.reader([line], delimiter=',', quotechar='"'))[0] ]
records.append(newLine)
return records

和往常一样,电池也包含在python中。这里使用的是标准libcsv模块:

import csv
with open(path, "r") as f:
csv_reader = csv.reader(f, delimiter=",")
for row_number, row in enumerate(csv_reader):
print(f"{row_number} => {row}")

如果stdlib由于某种奇怪的原因而不可用。。您需要用"分隔符"、"分隔符"one_answers"单元格值"标记每一行。同样,这对于stdlib(import re(来说是微不足道的。让我们假设你根本没有电池,只有plain python

您需要意识到,如何处理每行中的每个字符取决于"上下文",并且该上下文是由以前的所有字符建立的。这里建议使用堆栈。从堆栈中推送和弹出状态(也称为上下文(取决于当前上下文是什么(堆栈的顶部(和您正在处理的当前角色。现在,给定一个上下文,您可以根据上下文对每个字符进行不同的处理:

class State: 
IN_NON_DELIMITED_CELL = 1 
IN_DELIMITED_CELL = 2 
def get_cell_values(line, quotechar='"', separator=','): 
stack = [] 
stack.append(State.IN_NON_DELIMITED_CELL) 
cell_values = [""] 
for character in line: 
current_state = stack[-1] 
if current_state == State.IN_NON_DELIMITED_CELL: 
if character == quotechar: 
stack.append(State.IN_DELIMITED_CELL) 
elif character == separator: 
cell_values.append("") 
else: 
cell_values[-1] += character 
if current_state == State.IN_DELIMITED_CELL: 
if character == quotechar: 
stack.pop() 
else: 
cell_values[-1] += character 
return cell_values 
with open(path, "r") as f:
for line in f:
cell_values = tokenize(line, quotechar='"', delimiter=',')
print(cell_values)

这是一个很好的起点:

print(get_cell_values('"this","is",an,example,of,"doing things, the hard way?"'))
# prints:
['this', 'is', 'an', 'example', 'of', 'doing things, the hard way?']

为了进一步了解这一点,请研究以下主题:字符串标记化、LL+LR解析器、递归下降、移位减少解析器。

最新更新