我正在尝试清理代码块,因此不必使用多个文件处理程序。
但是,我需要使用csv才能按值(逗号分隔)读取文件中的行,但是随后我需要常规的文件功能来替换文本。
无论如何,我可以使用以下代码最小化文件处理程序的使用:
api = Trading(config_file='ebay.yaml')
f = open("row_data.csv")
csv_f = csv.reader(f)
for row in csv_f:
desktop_images_link = row[1]
desktop_images = desktop_images_link.split('|')
for x in desktop_images:
files = {'file': ('EbayImage', open(x, 'rb'))}
api.execute('UploadSiteHostedPictures', files=files)
dictstr = api.response.dict()
hosted_url = dictstr["SiteHostedPictureDetails"]["FullURL"]
o = open("row_data.csv").read()
o = o.replace(x,hosted_url)
w = open("row_data.csv",'w')
w.write(o)
w.close()
答案 0 :(得分:1)
您实际上不需要将文件作为文本读取到replace
图片网址。这些值不会出现在文件的其他任何位置,而是出现在当前行的当前列中。因此,您无需在整个文件的内容上调用replace
,只需在当前行的当前列上调用即可。
这意味着您可以逐行转换CSV。
写入临时文件,然后将其移到原始文件上比在原位覆盖文件要好。这样,如果您在写入过程中绊倒了电源线,则您将拥有完整的原始文件或完整的新文件,而不是新文件的一半,而其他所有文件将永远丢失。这也更加有效-我们可以一次打开两个文件,而不必在内存中存储超过当前行的文件。而且更简单-不必担心同一个文件的两个句柄之间的任何冲突,因为您永远不会有同一个文件的两个句柄。
在我们这样做的时候,您甚至不需要在这里replace
。第1列是通过管道传输的原始图像。您split
将它们分成单独的字符串。您想用另一个字符串完全替换那些字符串之一。您可以在没有replace
的情况下执行此操作-只需使用其他字符串代替原始字符串即可。
所以,您想要的是这样的:
with open("row_data.csv") as fin, open("row_data.csv.tmp", "w") as fout:
csv_in = csv.reader(fin)
csv_out = csv.writer(fout)
for row in csv_in:
desktop_images_link = row[1]
desktop_images = desktop_images_link.split('|')
replacement_images = [hosted_url for desktop_image in desktop_images]
row[1] = '|'.join(replacement_images)
csv_out.writerow(row)
os.replace('row_data.csv.tmp', 'row_data.csv')
就是这样。
如果您真的需要全局替换图像,因为它们可能会任意出现在文件中其他行的其他列中,则您仍可以改进代码,使其更简单,并且解决一个严重的问题。
问题在于,在row_data.csv
中的行循环中,您open("row_data.csv", "w")
并覆盖了整个文件。你不能那样做。您要做的是以下之一:
replace
,然后将其写到末尾。最后一个可能是最简单的,并且(除了第一个之外)是最有效的。
在处理此问题时,您应该使用with
语句来确保关闭所有文件对象。
所以:
all_desktop_images = []
with open("row_data.csv") as f:
csv_f = csv.reader(f)
for row in csv_f:
desktop_images_link = row[1]
desktop_images = desktop_images_link.split('|')
all_desktop_images.extend(desktop_images)
with open("row_data.csv") as f:
data = f.read()
for desktop_image in all_desktop_images:
data = data.replace(desktop_image, hosted_url)
with open("row_data.csv", "w") as f:
f.write(data)
在源代码中,我们对open
的调用次数仍然相同,但是现在每个调用仅执行一次,而不是一遍又一遍地打开和重新打开(并覆盖)文件,一次只能打开其中一个,而不是一次打开所有三个。