csv writer无法正确打印行

时间:2014-05-10 18:17:04

标签: python csv

我有一个csv脚本,它在一组收集的URL上运行,如下所示:threaded(urls,write_csv,num_threads = 5)。该脚本正确写入csv但似乎重写了每个url的第一行,而不是为每个后续传递的url写入新行。结果是最终的csv有一行包含来自最后一个url的数据。我是否需要添加计数器和索引才能完成此操作或完全重构程序?这是相关代码:

import csv
from thready import threaded

def get_links():
    #gather urls
    threaded(urls, write_csv, num_threads=5)

def write_csv(url):
    #the data dict with values that were previously assigned is defined here
    data = {
            'scrapeUrl': url,
            'model': final_model_num,
            'title': final_name, 
            'description': final_description, 
            'price': str(final_price), 
            'image': final_first_image, 
            'additional_image': final_images,
            'quantity': '1', 
            'subtract': '1', 
            'minimum': '1', 
            'status': '1', 
            'shipping': '1' 
        } 
        #currently this writes the values but only to one row even though multiple urls are passed in
        with open("local/file1.csv", "w") as f:
            writer=csv.writer(f, delimiter=",")
            writer.writerows([data.keys()])
            writer.writerow([s.encode('ascii', 'ignore') for s in data.values()])

if __name__ == '__main__':
    get_links()

2 个答案:

答案 0 :(得分:1)

以写入模式打开文件会删除文件中已有的文件(如文档here所示)。如果你有多个线程打开同一个文件,那么最后一个打开文件将会#34; win"并将其数据写入文件。其他人将用最后一个数据覆盖他们的数据。

您应该重新考虑您的方法。对文件等外部资源的多线程访问必然会导致问题。更好的想法是让代码的线程部分仅从URL中检索数据,然后将其返回到将数据按顺序写入文件的单线程部分。

如果你只有少量网址,你可以完全省去线程,只需编写一个循环遍历网址,打开文件一次,然后写入所有数据。

答案 1 :(得分:1)

似乎有一个问题就是这条线......

with open("local/file1.csv", "w") as f:

每个函数调用都会覆盖输出文件(“w”表示文件模式为write)。在写入模式下打开现有文件时,将清除该文件。由于每次调用该函数时都会清除该文件,因此它只显示一行。

更大的问题是,多个线程写入单个文件并不是一种好习惯。

你可以试试这个......

valid_chars = "-_.() abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
filename = ''.join(c for c in url if c in valid_chars)
with open("local/%s.csv" % filename, "w") as f:
    # rest of code...

...将每个网址写入不同的文件(假设网址是唯一的)。然后,您可以稍后重新组合这些文件。更好的方法是将数据放入队列中,并在调用线程后将其全部写入。像这样......

import Queue
output_queue = Queue.Queue()

def get_links():
    #gather urls
    urls = ['www.google.com'] * 25
    threaded(urls, write_csv, num_threads=5)

def write_csv(url):
    data = {'cat':1,'dog':2} 
    output_queue.put(data)

if __name__ == '__main__':

    get_links() # thready blocks until internal input queue is cleared

    csv_out = csv.writer(file('output.csv','wb'))

    while not output_queue.empty():
        d = output_queue.get()
        csv_out.writerow(d.keys())
        csv_out.writerow(d.values())