2013-05-03 63 views
0

這是工作,但是很慢。需要加快這個Python腳本 - 我認爲StringIO非常慢

我寫了一個自定義.py將.gpx轉換爲.kml。它的工作就像我需要的,但它太慢了:對於477k的小.gpx,它正在寫一個207k.kml文件,需要198秒才能完成!這是荒謬的,我還沒有得到一個肉味.gpx大小呢。

我的預感是,它是如此緩慢的stringIO.stringIO(x)。任何想法如何加快它?

感謝您的期待。

這裏只重點剪刀:

f = open(fileName, "r") 
x = f.read() 
x = re.sub(r'\n', '', x, re.S) #remove any newline returns 
name = re.search('<name>(.*)</name>', x, re.S) 
print "Attachment name (as recorded from GPS device): " + name.group(1) 

x = re.sub(r'<(.*)<trkseg>', '', x, re.S) #strip header 
x = x.replace("</trkseg></trk></gpx>",""); #strip footer 
x = x.replace("<trkpt","\n<trkpt"); #make the file in lines 
x = re.sub(r'<speed>(.*?)</speed>', '', x, re.S) #strip speed 
x = re.sub(r'<extensions>(.*?)</extensions>', '', x, re.S) # strip out extensions 

然後

#.kml header goes here 
kmlTrack = """<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.ope......etc etc 

然後

buf = StringIO.StringIO(x) 
for line in buf: 
      if line is not None: 
        timm = re.search('time>(.*?)</time', line, re.S) 
        if timm is not None: 
          kmlTrack += ("   <when>"+ timm.group(1)+"</when>\n") 
          checkSumA =+ 1 
buf = StringIO.StringIO(x) 
for line in buf: 
      if line is not None: 
        lat = re.search('lat="(.*?)" lo', line, re.S) 
        lon = re.search('lon="(.*?)"><ele>', line, re.S) 
        ele = re.search('<ele>(.*?)</ele>', line, re.S) 
        if lat is not None: 
          kmlTrack += ("   <gx:coord>"+ lon.group(1) + " " + lat.group(1) + " " + ele.group(1) + "</gx:coord>\n") 
          checkSumB =+ 1 
if checkSumA == checkSumB: 
      #put a footer on 
      kmlTrack += """  </gx:Track></Placemark></Document></kml>""" 
else: 
      print ("checksum error") 
      return None 

with open("outFile.kml", "a") as myfile: 
      myfile.write(kmlTrack) 
return ("succsesful .kml file-write completed in :" + str(c.seconds) + " seconds.") 

再次,這是工作,但它是很慢。如果有人能看到如何加快速度,請告訴我!乾杯


修訂

感謝的建議,所有的。我是Python的新手,並讚賞聽到關於分析。發現了它。將它添加到我的腳本中。它看起來像是一件事情,209秒總共運行208次,發生在一行中。這裏是一個剪輯:

ncalls tottime percall cumtime percall filename:lineno(function) 
.... 

4052 0.013 0.000 0.021 0.000 StringIO.py:139(readline) 
8104 0.004 0.000 0.004 0.000 StringIO.py:38(_complain_ifclosed) 
    2 0.000 0.000 0.000 0.000 StringIO.py:54(__init__) 
    2 0.000 0.000 0.000 0.000 StringIO.py:65(__iter__) 
4052 0.010 0.000 0.033 0.000 StringIO.py:68(next) 
8101 0.018 0.000 0.078 0.000 re.py:139(search) 
    4 0.000 0.000 208.656 52.164 re.py:144(sub) 
8105 0.016 0.000 0.025 0.000 re.py:226(_compile) 
    35 0.000 0.000 0.000 0.000 rpc.py:149(debug) 
    5 0.000 0.000 0.010 0.002 rpc.py:208(remotecall) 
...... 

有4個電話52秒每個電話。 cProfile表示它發生在144行,但我的腳本只能行到94行。我如何繼續?非常感謝。

+3

試用cStringIO? (儘管我自己懷疑477K字符串上的正則表達式,請使用探查器而不是猜測。) – geoffspear 2013-05-03 03:03:46

+0

@Wooble +1 - 這是一個沒有成果的方法。不要猜測。剖析你的代碼。 http://docs.python.org/2/library/profile.html – 2013-05-03 03:08:35

+0

將xml格式轉換爲另一種格式的最佳方式是使用xml/xpath/xsl。 – tdelaney 2013-05-03 04:08:42

回答

3

好的,謝謝大家。 cProfile顯示這是一個re.sub的調用,儘管我最初不確定哪一個 - 儘管有一些試驗和錯誤,但沒有花很長時間來隔離它。解決方案是將re.sub從「貪婪」轉爲「不貪婪」。

所以舊的標題條通話是x = re.sub(r'<(.*)<trkseg>', '', x, re.S) #strip header 現在變成x = re.sub(r'<?xml(.*?)<trkseg>', '', x, re.S) #strip header REALLY fast

它現在即使在零秒內也能保持重度的.gxp轉換。 ?有什麼不同!