python zwQTBox下down_stk_all修改为多进程及遇到的问题

在mac环境下,使用PyCharm和Anaconda3.6,通过tushare获取股票历史数据时,发现单进程速度较慢,尝试使用多进程加快速度。但在使用pool.apply实现多进程时,程序卡住。经过调试发现,问题出在_getproxies_macosx_sysconf函数返回空值。注释掉相关代码后,多进程可以正常运行并成功获取数据。最后调整为非阻塞的多进程池实现,实现了数据的快速下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境 :mac + pycharm + anaconda(配置3.6)

问题,用tushare的get_h_data取数据的时候,单进程太慢,想着用多进程跑起来:

def down_stk_all(qx,finx):
    '''
    根据finx股票列表文件,下载所有,或追加日线数据
    自动去重,排序
    
    '''
    dinx = pd.read_csv(finx,encoding='gbk') ;print(finx);
    xn9=len(dinx['code']);
    # for i,xc in enumerate(dinx['code']):
    #     code="%06d" %xc
    #     print("\n",i,"/",xn9,"code,",code)
    #     #---
    #     qx.code=code;
    #     down_stk_cn010(qx);
    pool = multiprocessing.Pool(processes=16)
    for i,xc in enumerate(dinx['code']):
        code="%06d" %xc
        print("\n",i,"/",xn9,"code,",code)
        #---
        qx.code=code;
        # down_stk_cn010(qx);
        pool.apply(down_stk_cn010,(qx,)) 
    pool.close()
    pool.join() 


def down_stk_cn010(qx):
    ''' 中国A股数据下载子程序
    【输入】
        qx (zwDatX): 
        xtyp (str):数据类型,9,Day9,简版股票数据,可下载到2001年,其他的全部是扩充版数据,只可下载近3年数据
            D=日k线 W=周 M=月 默认为D
    :ivar xcod (int): 股票代码
    :ivar fss (str): 保存数据文件名
    '''
    
    xcod,rss,=qx.code,qx.rDay;
    tim0='1994-01-01';#tim0='2012-01-01';
    #
    fss=rss+xcod+'.csv'
    #-------------------
    xfg=os.path.exists(fss);xd0=[];xd=[];
    if xfg:
        xd0= pd.read_csv(fss,index_col=0,parse_dates=[0],encoding='gbk') 
        #print(xd0.head())
        xd0=xd0.sort_index(ascending=False);
        #tim0=xd0.index[0];
        _xt=xd0.index[0];#xt=xd0.index[-1];###
        s2=str(_xt);tim0=s2.split(" ")[0]
        
    print('\n',xfg,fss,",",tim0);   
    #-----------    
    try:
        xd=ts.get_h_data(xcod,start=tim0,end=None,retry_count=5,pause=1)     #Day9
        #xd=ts.get_hist_data(xcod,start=tim0,end=None,retry_count=5,pause=1,ktype=xtyp);
        #-------------
        if xd is not None:
            if (len(xd0)>0):         
                xd2 =xd0.append(xd)                
                #  flt.dup 
                xd2["index"]=xd2.index
                xd2.drop_duplicates(subset='index', keep='last', inplace=True);
                del(xd2["index"]);
                #xd2.index=pd.to_datetime(xd2.index)
                xd=xd2;
                
            xd=xd.sort_index(ascending=False);   
            xd=np.round(xd,3);
            xd.to_csv(fss,encoding='gbk')
    except IOError: 
        pass    #skip,error
    
           
    return xd  





源代码注释掉了,for循环挨个取。用多进程,扔到进程池里,这样快很多。

问题来了,因为用的pool.apply,阻塞方式,跑起来以后卡住不动了。

一路追踪:_parse_fq_data --> urlopen --> build_opener -->

    for klass in default_classes:
        opener.add_handler(klass())
跟进:

class ProxyHandler(BaseHandler):
    # Proxies must be in front
    handler_order = 100

    def __init__(self, proxies=None):
        if proxies is None:
            proxies = getproxies()
        assert hasattr(proxies, 'keys'), "proxies must be a mapping"
        self.proxies = proxies
        for type, url in proxies.items():
            setattr(self, '%s_open' % type,
                    lambda r, proxy=url, type=type, meth=self.proxy_open:
                        meth(r, proxy, type))


    def getproxies():
        return getproxies_environment() or getproxies_macosx_sysconf()

getproxies_environment()没问题,返回为空。

getproxies_macosx_sysconf()出事了,卡住不动弹了。

    def getproxies_macosx_sysconf():
        """Return a dictionary of scheme -> proxy server URL mappings.

        This function uses the MacOSX framework SystemConfiguration
        to fetch the proxy information.
        """
        return _get_proxies()

想进入_get_proxies 跟踪的时候,代码飞了。

点击代码跟进,来到这里。

# encoding: utf-8
# module _scproxy
# from 省略路径/anaconda/envs/for36/lib/python3.6/lib-dynload/_scproxy.cpython-36m-darwin.so
# by generator 1.145
# no doc
# no imports

# functions

def _get_proxies(*args, **kwargs): # real signature unknown
    pass

def _get_proxy_settings(*args, **kwargs): # real signature unknown
    pass

# no classes
# variables with complex values

__loader__ = None # (!) real value is ''

__spec__ = None # (!) real value is ''

这段代码在:

省略路径/Library/Caches/PyCharm2017.1/python_stubs/720200485/_scproxy.py下。惆怅,我python纯新爪。

单独跑了一次,就取一只的数据,发现getproxies_macosx_sysconf返回的是空!!!!

what,还能这样???难道是多进程的时候抢占系统资源了???

反正是空,那就注释掉你!

    def getproxies():
        return getproxies_environment() #or getproxies_macosx_sysconf()

跑起来吧。。能取到数据了,泪流满面。

修改pool方式为非阻塞。

最终代码:

def down_stk_all(qx,finx):
    '''
    根据finx股票列表文件,下载所有,或追加日线数据
    自动去重,排序
    
    '''
    dinx = pd.read_csv(finx,encoding='gbk') ;print(finx);
    xn9=len(dinx['code']);
    # for i,xc in enumerate(dinx['code']):
    #     code="%06d" %xc
    #     print("\n",i,"/",xn9,"code,",code)
    #     #---
    #     qx.code=code;
    #     down_stk_cn010(qx);
    pool = multiprocessing.Pool(processes=8)
    for i,xc in enumerate(dinx['code']):
        qxtemp= copy.deepcopy(qx)
        code="%06d" %xc
        # print("\n",i,"/",xn9,"code,",code)
        #---
        qxtemp.code=code;
        # down_stk_cn010(qx);
        pool.apply_async(down_stk_cn010,(qxtemp,))  # 维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
    pool.close()
    pool.join()  # 调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束

小问题还是有,比如tushare的进度条就费了,print到一起了。

不过,享受多进程同时下载的快感吧。。。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值