【问题标题】:Efficiently processing a very large unicode string into csv有效地将一个非常大的 unicode 字符串处理成 csv
【发布时间】:2016-01-27 17:33:16
【问题描述】:

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

我从泰克示波器下载了大约 5000 万长的 unicode 字符串。分配这个对于内存来说是一件痛苦的事情(sys.getsizeof() 报告 ~100 MB)

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

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

代码 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 表中,然后将 CSV 提取到 10,000 个样本块中(这是脚本的预期目的)。但我不想这样做!

感谢大家的帮助!

【问题讨论】:

  • 嗨 Prune,感谢您的意见。我还没有尝试过 cStringIO .... 将不得不尝试它。如果在读取/解析方法中您的意思是从范围一 10k 块而不是 10m 块读取,我不能这样做。我正在做 req 背后的想法特别是拉力很大(10m 连续点,10k 块不会是连续的。尽管现在我考虑了一下,我可以将 10m 存储为保存的波形并从中读取块!谢谢你的想法!!)
  • 我将之前的评论变成了更有效处理的答案。 /// 我的意思是让您读取对您的应用程序有效的任何块大小。您通常可以通过在处理当前块时让(较慢的)读取获取下一个块来加快速度。这是过去的简单缓冲。
  • 有道理;对于我的应用程序,我需要一次获取所有 10m 样本。我忘记了示波器实际上可以存储这 10m 个样本,然后我可以从存储的波形中逐块读取,而不是一次下载整个实时源!有没有办法并行化这个过程?似乎 Python 不会在一个 (ppsinst.query('CURVE?") 完成之前执行一个到下一个命令。

标签: python data-acquisition


【解决方案1】:

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


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

简而言之,您创建了一个函数来体现您希望并行运行的过程。然后,您创建一个使用该函数作为 target 参数的进程。然后开始该过程。当您想将其线程合并回主程序时,请使用 join

【讨论】:

  • 将糟糕的 PC 从 3gb Ram 升级到 16gb 解决了使用 Code 1 方法的内存问题!
【解决方案2】:

看看 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

【讨论】:

  • 如果时间允许会试一试,还没试过这个方法!
  • from buffer 是一个很好的建议,但不幸的是,没有办法先验地知道 10k csv 有多少。让我解释;字符串由这种提要组成; ...127,23,1,100,-3,24... 因为 fromBuffer 需要确切知道要提取多少个字符,所以我无法提前知道提取 10k 逗号分隔值的参数。这将需要提取一些任意数字,通过提取的内容进行处理以计算逗号的数量并重复(可能对二等分搜索给出了上限和下限?)。除非我误解了 fromBuffer 的工作原理?
  • 明白。您需要有固定数量的字节才能使 frombuffer 正常工作。
猜你喜欢
  • 2020-08-23
  • 1970-01-01
  • 2014-10-11
  • 2011-05-13
  • 2012-10-03
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多