Python:csv 到 pickle 表示,返回到 csv 会混淆文件内容

Python: csv to pickle representation, back to csv messes with file content

我正在尝试 pickle 一个 csv 文件,然后将其 pickled 表示变回 csv 文件。

这是我想出的代码:

from pathlib import Path
import pickle, csv

csvFilePath = Path('/path/to/file.csv')

pathToSaveTo = Path('/path/to/newFile.csv')

csvFile = open(csvFilePath, 'r')
f = csvFile.read() 
csvFile.close() 

f_pickled = pickle.dumps(f) 


f_unpickled = pickle.loads(f_pickled) 

#save unpickled csv file
new_csvFile = open(pathToSaveTo, 'w')
csvWriter = csv.writer(new_csvFile)
csvWriter.writerow(f_unpickled)
new_csvFile.close()

newFile.csv 已创建,但其内容存在两个问题:

  1. 现在每个字符之间有一个逗号。
  2. 现在每行后面都有一对引号。

我需要对我的代码进行哪些更改才能获得 file.csv 的精确副本?

我认为问题在于您尝试编写 CSV 文件的方式,pickling 和 unpickling 没问题。如果将 f 与 f_unpickled 进行比较:

if f==f_unpickled:
    print("Same")

这是在我的案例中打印的。如果打印类型,您会看到两个字符串。

更好的选择是遵循 document style 并一次写入每一行,而不是将整个字符串包括新行。像这样:

from pathlib import Path
import pickle, csv

csvFilePath = Path('file.csv')

pathToSaveTo = Path('newFile.csv')

rows = []
csvFile = open(csvFilePath, 'r')
with open(csvFilePath, 'r') as file:
    reader = csv.reader(file)
    for row in reader:
        rows.append(row)

# pickle and unpickle        
rows_pickled = pickle.dumps(rows) 
rows_unpickled = pickle.loads(rows_pickled) 
if rows==rows_unpickled:
    print("Same")

#save unpickled csv file
with open(pathToSaveTo, 'w', newline='') as csvfile:
    csvWriter = csv.writer(csvfile)
    for row in rows_unpickled:
        csvWriter.writerow(row)

这在我测试时有效——尽管需要更多地使用行分隔符才能在末尾没有空行。

问题是你正在读取文件的原始文本,f = csvFile.read()然后,在写入时,你正在提供数据,这是一个文本块,全部在一个字符串中,虽然是 CSV writer 对象。 CSV writer 会将字符串视为可迭代对象,并将每个可迭代元素写入 CSV 单元格中。然后,第二行没有数据,流程结束。

你执行的 pickle dumpsloads 只是一个空操作:那里什么都没有发生,如果有任何问题,那宁愿是由于您要传递给 dumps 的对象:当 loads 被调用时,您会得到一个异常,并且没有不同的数据。

现在,不告诉你为什么要这样做,以及你为数据计划了哪些中间步骤,很难告诉你:你正在执行两个非操作:读取文件,pickling 和 unpickling 它的内容,并将这些内容写回磁盘。

在什么情况下您需要将这些数据结构化为行或 CSV 单元格?只需在需要的地方应用适当的转换,就大功告成了。

如果你想让整个“什么都不做”的循环经历实际的 CSV 数据在 Python 中的不同元素中分离,你可以执行:

from pathlib import Path
import pickle, csv

csvFilePath = Path('file.csv')

pathToSaveTo = Path('newFile.csv')

data = list(csv.reader(open(csvFilePath))) 
# ^consumes all iterations of the reader: each iteration is a row, composed of a list where each cell value is a list elemnt
pickled_data = pickle.dumps(data)
restored_data = pickle.loads(pickled_data)
csv.writer(open(pathToSaveTo, "wt")).writerows(restored_data)

在此代码段中,数据是通过 csv.reader 读取的,而不是直接读取的。将它包装在列表调用中会导致所有行都被读取并转换为列表项 - 因为 reader 否则是一个惰性迭代器(并且它不会是可拾取的,因为它依赖于其状态的属性之一是打开文件)