使用线程

时间:2015-08-04 16:11:02

标签: python multithreading excel xlsxwriter

我正在尝试使用python中的xlswriter包将位置的地址写入我的Excel工作表。我面临的问题是当我尝试使用线程运行函数时,值不会写入工作表。请参阅以下代码:此处列出包含所有原始地址的列表。

import threading
import xlsxwriter
from geopy.geocoders import Nominatim

geolocator = Nominatim()
outputLocation = 'output.xlsx'
workbook = xlsxwriter.Workbook(outputLocation)
w_sheet4 = workbook.add_worksheet('openstreet')

def openstreet():
    p = 1
    for row in rows:        #rows consists of raw addresses

        try:
            rawAddress = str(" ".join(row[1].strip().split())) #here I am normalizing the addresses using openstreet api
            location = geolocator.geocode(rawAddress)
            w_sheet4.write(p, 1, rawAddress)
            w_sheet4.write(p, 2, str(location.address))
        except Exception as e:
            print "OpenStreet", e

        p += 1

t4 = threading.Thread(target=openstreet)
t4.start()

如果我不使用线程并通过调用它来运行该函数,我可以写入工作表。请参阅以下代码:

import threading
import xlsxwriter
from geopy.geocoders import Nominatim

geolocator = Nominatim()
outputLocation = 'output.xlsx'
workbook = xlsxwriter.Workbook(outputLocation)
w_sheet4 = workbook.add_worksheet('openstreet')

def openstreet():
    p = 1
    for row in rows:        #rows consists of raw addresses

        try:
            rawAddress = str(" ".join(row[1].strip().split())) #here I am normalizing the addresses using openstreet api
            location = geolocator.geocode(rawAddress)
            w_sheet4.write(p, 1, rawAddress)  #raw address
            w_sheet4.write(p, 2, str(location.address)) #normalize address
        except Exception as e:
            print "OpenStreet", e

        p += 1

#t4 = threading.Thread(target=openstreet)
#t4.start()
openstreet()

我使用线程的原因是因为我使用多个API(google,yahoo,openstreetmap API,bing)尝试规范化地址并进行比较。任何人都可以帮助我,当我使用线程而不是正常的函数调用时,为什么我无法写入工作表。

2 个答案:

答案 0 :(得分:1)

谨慎使用! XlsxWriter不是线程安全的。我发现如果你使用in_memory选项,它将使用SharedStrings并最终写入意外的单元格。我创建了一张机票atm:

Github discussion

来自XlsxWriter作者的更新:

  

_get_shared_string_index()中的SharedStrings方法并非如此   线程安全。该类中的其他方法应该是因为它们   仅从Workbook调用(对此应该只有一个唯一的   每个xlsxwriter对象的实例)或通过Workbook析构函数(当   应该连接工作表线程并停止活动。

     
    

我发现如果我使用in_memory选项,XlsxWriter将使用SharedStrings

  
     

无论您是否使用,都可以调用SharedStrings类   in_memory与否。 in_memory选项与临时使用有关   文件而不是SharedStrings(参见文档)。

     

如果您希望避免使用SharedStrings,从而避免锁定,那么   可以使用constant_memory模式。有一些警告   但是:数据需要按行列顺序编写,您无法使用   add_table()或merge_range()。请参阅Contructor文档(上面的链接)和   也在使用记忆和表现。

     
    

XlsxWriter还有什么需要我担心的吗?

  
     

可能,但没有任何想到的东西。

答案 1 :(得分:0)

我已经在函数末尾使用threading.join()解决了它。为什么我们需要使用join()可以从这个link中理解。以下代码对我有用。

import threading
import xlsxwriter
from geopy.geocoders import Nominatim

geolocator = Nominatim()
outputLocation = 'output.xlsx'
workbook = xlsxwriter.Workbook(outputLocation)
w_sheet4 = workbook.add_worksheet('openstreet')

def openstreet():
    p = 1
    for row in rows:        #rows consists of raw addresses

        try:
            rawAddress = str(" ".join(row[1].strip().split())) #here I am normalizing the addresses using openstreet api
            location = geolocator.geocode(rawAddress)
            w_sheet4.write(p, 1, rawAddress)
            w_sheet4.write(p, 2, str(location.address))
        except Exception as e:
            print "OpenStreet", e

        p += 1

t4 = threading.Thread(target=openstreet)
t4.start()
t4.join() #we need to use threading.join to make sure the thread function finishes before the main program exits