有效地将非常大的unicode字符串处理成csv

时间:2016-01-27 17:33:17

标签: python data-acquisition

通常我能够在这个网站上很快找到我的困境的答案,但也许这个问题需要更具体的触摸;

我从Tektronix示波器下载了大约5000万长的unicode字符串。获得此分配是一个痛苦的内存**(sys.getsizeof()报告~100 MB)

问题在于我需要将其转换为CSV,以便我可以获取1000万个Comma Sep值中的10,000个(这是固定的)...... 1)我尝试过split(“,”)方法,使用这个,python内核上的RAM使用SPIKES另外300 MB ....但是这个过程非常有效(除非我在一个例程中循环这个~100次)。 ..在迭代40-50之间,内核吐出内存错误。) 2)我编写了自己的脚本,在下载了荒谬的长字符串之后,扫描逗号的数量,直到我看到10,000并停止,将逗号之间的所有值转换为浮点数并填充np数组。从内存使用的角度来看,这非常有效(从导入文件之前到运行脚本之后,内存使用量只会改变150MB。)但是速度要慢得多,并且通常会在100x循环完成后不久导致内核崩溃。

以下是用于处理此文件的代码,如果您PM我,我可以向您发送一份字符串副本进行试验(但我相信它可能更容易生成一个)

代码1(使用split()方法)

PPStrace = PPSinst.query('CURV?')
PPStrace = PPStrace.split(',')
PPSvals = []
for iii in range(len(PPStrace)): #does some algebra to values
    PPStrace[iii] = ((float(PPStrace[iii]))-yoff)*ymult+yzero

maxes=np.empty(shape=(0,0))
iters=int(samples/1000)
for i in range(1000): #looks for max value in 10,000 sample increments, adds to "maxes"
    print i
    maxes = np.append(maxes,max(PPStrace[i*iters:(i+1)*iters]))
PPS = 100*np.std(maxes)/np.mean(maxes)
print PPS," % PPS Noise"

代码2(自生成脚本);

PPStrace = PPSinst.query('CURV?')
walkerR=1
walkerL=0
length=len(PPStrace)
maxes=np.empty(shape=(0,0))
iters=int(samples/1000) #samples is 10 million, iters then is 10000

for i in range(1000):
    sample=[] #initialize 10k sample list
    commas=0 #commas are 0
    while commas<iters: #if the number of commas found is less than 10,000, keep adding values to sample
        while PPStrace[walkerR]!=unicode(","):#indexes commas for value extraction
            walkerR+=1
            if walkerR==length:
                break
        sample.append((float(str(PPStrace[walkerL:walkerR]))-yoff)*ymult+yzero)#add value between commas to sample list
        walkerL=walkerR+1
        walkerR+=1
        commas+=1
    maxes=np.append(maxes,max(sample))
PPS = 100*np.std(maxes)/np.mean(maxes)
print PPS,"% PPS Noise"

还尝试使用StringIO进行Pandas Dataframe进行CSV转换。只要尝试将其读入帧中,该事就会出现内存错误。

我认为解决方案是将其加载到SQL表中,然后在10,000个样本块中拉出CSV(这是脚本的目的)。但我很乐意不这样做!

感谢你们的帮助!

2 个答案:

答案 0 :(得分:0)

看看numpy.frombuffer(http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.frombuffer.html)。这允许您指定计数和偏移量。您应该能够将大字符串放入缓冲区,然后以块的形式处理它,以避免巨大的内存峰值。

编辑2016-02-01

由于frombuffer需要有一个固定的字节宽度,我尝试了numpy.fromregex,它似乎能够快速解析字符串。它必须完成所有可能导致一些内存问题的事情。 http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.fromregex.html

这样的事情:

buf = StringIO.StringIO(big_string)
output = numpy.fromregex(buf, r'(-?\d+),', dtype=[('val', np.int64)])
# output['val'] is the array of values

答案 1 :(得分:0)

您是否尝试过课 cStringIO ?它就像文件IO一样,但是使用字符串作为缓冲区而不是指定的文件。坦率地说,我希望你患有慢性速度问题。您自己生成的脚本应该是正确的方法。如果你一次读取一个块,然后在下一个块正在读取时解析它,你可能会获得一些加速。

对于并行处理,请使用多处理包。有关详细信息和示例,请参阅official documentationthis tutorial

简而言之,您创建了一个体现您想要并行运行的进程的函数。然后,使用该函数创建一个流程作为目标参数。然后开始该过程。如果要将其线程合并回主程序,请使用 join