V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
slysly759
V2EX  ›  Python

请教一下 Python 多进程的内容

  •  
  •   slysly759 · 2016-07-22 16:37:05 +08:00 · 2694 次点击
    这是一个创建于 3075 天前的主题,其中的信息可能已经有所发展或是发生改变。

    #起因: 公司让处理大量 excel 数据并导入 oracle ,但是单进程太慢了,于是考虑多线程或多进程,在尝试过网络上很多版本的多线程多进程,但都导入部分数据后退出导致失败具体见下文

    #错误原因:

    pool=ThreadPool(4)
    cqs=cqs_branch_connect()
    name_list=cqs_pt_rating().get_path()
    connection_id=get_connectionid()
    batch_id=get_batch_id()
    conn_order_number=get_order_number()
    bug_connection_id=0
    cqs.make_exceldata(name_list,bug_connection_id,connection_id,batch_id,conn_order_number)
    excel_name='new 管道连接.xlsx'
    data_list=compliment(header_name,excel_name)
    pool.map(insert_db,data_list)
    
    
    ##data_list 少则有千条 多则有上万条,但是 map 加上 pool 并不能将 data_list 数据全额导入进数据库 在执行到开始的某一段就会产生 process Finnished by the code -13000xxxx 的代码 google 是没有相关内容 我想知道这是为什么 并渴望知道解决方案。
    ###1.我很好奇网上一些多进程的按照这个模式实现的时候 有没有遇到过当 data 过大过多 然后不执行这种情况
    ###2.我很想知道 多进程是如何在这些列表里面加锁,比如让进程 1 访问 list[1:10]进程二[11:20]....进程 8[80:90] 不让他们发生 race competation 或者如何通过数量来划分哪些列表归谁呢?
    
    
    ####PS:尝试过的并发: multipletreading 还是旗下的 dummy 亦或是 3.x 新出来的 concurrent.futures
    
    9 条回复    2016-08-01 23:40:49 +08:00
    fzinfz
        1
    fzinfz  
       2016-07-22 20:24:53 +08:00   ❤️ 1
    建议直接用 MS 家的 OLEDB ,然后用官方的 SqlBulkCopy 复制 Table 。
    C#代码参考:

    ```
    namespace XXX_SqlBulkCopy
    {
    class Program
    {
    static void Main(string[] args)
    {
    // Connection String to Excel Workbook
    string excelConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=yyy.xlsx;Extended Properties=""Excel 12.0;HDR=YES;""";

    // Create Connection to Excel Workbook
    using (OleDbConnection connection = new OleDbConnection(excelConnectionString))
    {
    OleDbCommand command = new OleDbCommand
    ("SELECT * FROM [backlog$]", connection);

    connection.Open();

    // Create DbDataReader to Data Worksheet
    using (DbDataReader dr = command.ExecuteReader())
    {
    // SQL Server Connection String
    string sqlConnectionString = "Data Source=.;Initial Catalog=XXX;Integrated Security=True";

    // Bulk Copy to SQL Server
    using (SqlBulkCopy bulkCopy =
    new SqlBulkCopy(sqlConnectionString))
    {
    bulkCopy.DestinationTableName = "backlog$";
    bulkCopy.WriteToServer(dr);
    }
    }
    }
    }
    }
    }


    ```
    zhuangzhuang1988
        2
    zhuangzhuang1988  
       2016-07-22 20:34:36 +08:00
    用 visualstudio 分析一下, 慢在哪里, 再优化..
    lizhenda
        3
    lizhenda  
       2016-07-22 21:02:19 +08:00
    可以先把数据按你开多少个进程分配好,然后再分别塞给各个进程···如果用抢占式会出现中间断开少文件的情况
    Aksura
        4
    Aksura  
       2016-07-22 21:09:08 +08:00
    建议将 excel 文件处理为文本文件,再用 sqlldr 将文本文件导入数据库。
    izoabr
        5
    izoabr  
       2016-07-22 21:36:00 +08:00
    何必呢,用工具直接导入不就得了,这事主要是考虑数据完整性,而不是创新性,所以我还是建议用工具,很多免费的工具都支持,能用就用着,有空再研究,而且不要在生产环境上研究。
    nyfwan123
        6
    nyfwan123  
       2016-07-23 08:47:35 +08:00 via Android
    建议手动
    slysly759
        7
    slysly759  
    OP
       2016-08-01 23:37:16 +08:00
    @fzinfz 我在这里统一做一下回复吧:问题解决了 看了国外的文献解决了这个迷之 bug 我把 map 换成了 map_async 虽然不明所以 但是解决了问题。
    这不是关键!关键是如果你认为插入数据库并发地插入那就大错特错了,他喵的 sql 有 excutemany 握草 刚好 cx_oracle 在第二章精通 oracle 和 python 写明了:如果不采用多条插入,那么是很浪费效率的。马丹不早说,我当时就把这个破玩儿重写了,效率提高一百倍有木有。一次性插入一百万条爽不爽~
    另外,应为是客户要求的,所以一些第三方什么 PLSQL 自带的 excel 导入工具啊 楼下说的 sqlldr 的轮子啊 都不符合要求,客户要的就是一键导入(当然后续又加了什么备份还原啊 上传 SFTP 啊)所以还是硬着头皮上了
    slysly759
        8
    slysly759  
    OP
       2016-08-01 23:37:49 +08:00
    @zhuangzhuang1988 我统一回复啦~
    slysly759
        9
    slysly759  
    OP
       2016-08-01 23:40:49 +08:00
    @lizhenda 我的数据都做成字典扔进 list 啦 其实我主要是不太清楚 pool.map 的原理(我没看源码别打我蛤)比如我的 list 有七个 进程并行的有两个,那么按理说是一个一个扔进进程池里面直到没有了为止。应该是这样。
    对于你说的这次数据库还没有遇到,我想不远的时候会用到你说的文件锁或者进程间通信之类的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2418 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 94ms · UTC 00:26 · PVG 08:26 · LAX 16:26 · JFK 19:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.