Python Pandas Threading读取read_fwf

时间:2018-12-11 04:55:29

标签: python pandas

此处是新手式python / pandas用户。我一直在read_fwf中使用chunksize arg并迭代变量的value_counts。我编写了一个函数来传递args(例如fileiterator)和变量以进行解析和计数。我希望能够并行化此功能,并且能够同时将2个文件读取到同一功能中。 它的确起作用了……但是,我的速度变慢了。线程同时完成,但是一个似乎正在减慢另一个(IO瓶颈?)。通过顺序而不是并行运行这些功能,我得到了更快的速度(324秒对172秒)。有想法吗?我执行错了吗?我已经尝试了多进程,但是出现了startmap错误,无法使fileiterator(read_fwf的输出)腌制。

testdf1=pd.read_fwf(filepath_or_buffer='200k.dat',header=None,colspecs=wlist,names=nlist,dtype=object,na_values=[''],chunksize=1000)    
testdf2=pd.read_fwf(filepath_or_buffer='200k2.dat',header=None,colspecs=wlist,names=nlist,dtype=object,na_values=[''],chunksize=1000)

def tfuncth(df,varn,q,*args):
    td={}
    for key in varn.keys():
        td[key]=pd.Series()
    for rdf in df:
        if args is not None:
            for arg in args:
                rdf=eval(f"rdf.query(\"{arg}\")")
        for key in varn.keys():
            ecode=f'rdf.{varn[key]}.value_counts()'
            td[key]=pd.concat([td[key],eval(ecode)])
            td[key]=td[key].groupby(td[key].index).sum()
    for key in varn.keys():
        td[key]=pd.DataFrame(td[key].reset_index()).rename(columns={'index':'Value',0:'Counts'}).assign(Var=key,PCT=lambda x:round(x.Counts/x.Counts.sum()*100,2))[['Var','Value','Counts','PCT']]
    q.put(td)

  bands={
        '1':'A',
        '2':'B',
        '3':'C',
        '4':'D',
        '5':'E',
        '6':'F',
        '7':'G',
        '8':'H',
        '9':'I'
    }
    vdict={
        'var1':'e1270.str.slice(0,2)',
        'var2':'e1270.str.slice(2,3)',
        'band':'e7641.str.slice(0,1).replace(bands)'
    }

    my_q1=queue.Queue()
    my_q2=queue.Queue()
    thread1=threading.Thread(target=tfuncth,args=(testdf1,vdict,my_q1,flter1))
    thread2=threading.Thread(target=tfuncth,args=(testdf2,vdict,my_q2))
    thread1.start()
    thread2.start()

更新:

大量阅读后,这也是我得出的结论。我确信这是极其简化的结论,所以如果有人知道,请通知我。

  1. Pandas不是完全多线程友好的软件包

    • 显然有一个名为“ dask”的软件包,它可以复制许多熊猫函数。因此,我将对此进行调查。
  2. Python并不是真正的多线程兼容语言 情况

    • Python受其编译器约束。在纯python中,它由GIL解释和绑定,一次只能执行一个线程
      • 可以拆分多个线程,但只能并行处理非cpu绑定的函数。
      • 我的代码包含IO和CPU。简单的IO可能会并行运行,但会在处理器上等待执行。
      • 我计划通过编写仅IO操作并尝试线程化来对此进行测试。
    • 可以使用在线程上没有全局解释器锁(GIL)的其他编译器来编译Python。
      • 因此,诸如“ dask”之类的软件包可以利用多线程。

1 个答案:

答案 0 :(得分:0)

我确实设法通过使用多处理程序包使它工作并解决了我的问题。我遇到了两个问题。
1)多处理程序包与Juypter Notebook不兼容

2)您不能腌制熊猫阅读器的句柄(将多重处理的腌制对象传递给进程)。

我通过在Notebook环境之外进行编码来固定1,并通过向每个进程传递打开分块文件所需的参数来固定2,并让每个进程开始读取自己的块。

完成这两项操作后,与顺序运行相比,我的速度提高了60%。