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 已创建,但其内容存在两个问题:
- 现在每个字符之间有一个逗号。
- 现在每行后面都有一对引号。
我需要对我的代码进行哪些更改才能获得 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 dumps
和 loads
只是一个空操作:那里什么都没有发生,如果有任何问题,那宁愿是由于您要传递给 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 否则是一个惰性迭代器(并且它不会是可拾取的,因为它依赖于其状态的属性之一是打开文件)
我正在尝试 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 已创建,但其内容存在两个问题:
- 现在每个字符之间有一个逗号。
- 现在每行后面都有一对引号。
我需要对我的代码进行哪些更改才能获得 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 dumps
和 loads
只是一个空操作:那里什么都没有发生,如果有任何问题,那宁愿是由于您要传递给 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 否则是一个惰性迭代器(并且它不会是可拾取的,因为它依赖于其状态的属性之一是打开文件)