各位老师傅们, python2 支持异步 I/O 编程吗? - V2EX
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
Zioyi
V2EX    Python

各位老师傅们, python2 支持异步 I/O 编程吗?

  •  
  •   Zioyi 2017-08-19 10:39:14 +08:00 8684 次点击
    这是一个创建于 2980 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在下小白,在网上找了很多异步 I/O 教程,都是关于 python3 的 asyncio。python2 只有 yield、send 吗

    第 1 条附言    2017-08-19 15:18:56 +08:00
    感谢各位老师傅的意见,我再补充一下我的目的吧:
    我现在 200 万条数据要向数据库中插入。当前的做法是开多线程( 50 个),设置数据库锁去做插入,耗时 14 分钟(单线程跑要 40 分钟)。想让速度更快一些,用异步 I/O 编程实现( python2.7.13 )可行吗?
    21 条回复    2017-08-23 15:17:49 +08:00
    shawlib
        1
    shawlib  
       2017-08-19 10:52:37 +08:00
    什么系统?
    BBCCBB
        2
    BBCCBB  
       2017-08-19 10:56:13 +08:00
    python2 就用 gevent 咯
    Zioyi
        3
    Zioyi  
    OP
       2017-08-19 10:56:50 +08:00
    windows? 难道说 linux 的 python2 支持?
        4
    shawlib  
       2017-08-19 10:59:26 +08:00
    windows 不支持 signal(),我也是刚刚遇到这个问题,还不知道怎么解决
    shawlib
    SearchDream
        5
    SearchDream  
       2017-08-19 11:34:38 +08:00 via iPhone
    试试 Tornado
    NoAnyLove
        6
    NoAnyLove  
       2017-08-19 12:19:34 +08:00   1
    即使是 Python 3 asyncio 在 Windows 上也是不支持异步文件操作的,我也很绝望啊,明明 ProactorEventLoop 用的 IOCP 是支持文件读写的,完全不知道为啥独裁者大人不开发对应的文件支持功能,搜索了半天也没搜索到结果和原因,全程懵逼状态。。。。。。

    还是得看你具体什么 I/O 操作,是在什么操作系统上,至少 Windows 上的文件和 socket 是不同的。而且,如果是用 select 也可以被称作异步 I/O,只不过没有用到协程罢了。你的问题有点太宽泛了,不够具体。

    另外,如果你会搜索的话,就会知道,还有个东西叫做 Trollius
    lcdtyph
        7
    lcdtyph  
       2017-08-19 13:10:48 +08:00 via iPhone
    纯异步的话可以试试 pyuv,是基于 libuv 封装的,在 win 上底层是 iocp
    aheadlead
        8
    aheadlead  
       2017-08-19 16:00:42 +08:00
    不试试 executemany 吗?
    JhZ7z587cYROBgVQ
        9
    JhZ7z587cYROBgVQ  
       2017-08-19 16:07:42 +08:00
    附议 executemany 啊
    wucao219101
        10
    wucao219101  
       2017-08-19 16:09:45 +08:00
    Twisted
    realpg
        11
    realpg  
    PRO
       2017-08-19 16:25:07 +08:00
    啥数据库?
    ghostheaven
        12
    ghostheaven  
       2017-08-19 16:31:01 +08:00 via Android
    你确定性能瓶颈在 python 吗
    director
        13
    director  
       2017-08-19 23:20:20 +08:00
    mark
    NoAnyLove
        14
    NoAnyLove  
       2017-08-20 00:04:56 +08:00   1
    那么问题来了,具体是什么数据库?经过什么中间架构进行连接的吗(比如是不是要经过 HTTP 请求对数据库进行操作)?还是直接对数据库进行操作?用的什么 Python 库对数据进行操作?

    如果要高效地对数据库进行异步操作,那么操作数据库的 Python 库也必须是异步的,比如 aiomysql。asyncio 至少需要 3.3 才能支持,如果你坚持使用 Python 2 的话,可以选择 gevent,并且搭配支持 gevent 的异步数据库操作库,比如 ultramysql

    话说,既然你的并发依赖的是数据本身提供的锁机制,为什么会觉得瓶颈是因为 Python 线程的竞争?你在 Python 上还做了什么同步机制?
    Zioyi
        15
    Zioyi  
    OP
       2017-08-20 11:31:37 +08:00
    抱歉没有说明清楚,我使用的是 mysql 数据库,使用的 python 库是 pymysq。我使这里设置锁的原因是:我每一个线程都有一个连接数据库的链接(或者说是保持连接的句柄),如果我不加锁地去跑 50 个线程,会出现(Lock wait timeout exceeded; try restarting transaction)的报错,所以我在这里设置锁去保证同时只有一个线程去对数据库操作:
    ```
    if self.mysql_lock.acquire():
    cursor.execute(current_insert_sql)
    connection.commit()
    self.mysql_lock.release()
    ```
    不知我这种设计是否合理?
    NoAnyLove
        16
    NoAnyLove  
       2017-08-20 11:53:05 +08:00   1
    @Zioyi 没遇到过这种情况,不过感觉(Lock wait timeout exceeded; try restarting transaction)是因为你的并发太高了?不过如果使用了 Lock,同时只有一个线程对数据库读写的话,那么感觉有点跑不够。几个选择:

    1. 把 lock 换成 threading.BoundedSemaphore,然后设置一个合适的并发值(多试几次,找出一个合理的值,记得对报错的情况要 try-except )
    2. 直接引入 gevent, monkey.patch_all(),并发 50 个协程,如果出现同样的错误提示,那么很可能是并发高了,同样可以引入 gevent.lock.BoundedSemaphore 来控制并发数,或者减少协程数目。

    如果出现了 2 这种情况,使用协程和多线程的性能差距应该不会特别大。异步 I/O 的性能高需要有足够高的并发数,如果瓶颈是在并发数上,你还可以试试更换其他操作 MySQL 的 Python 库,比如我前面提到的 ultramysql,主页上写的这个库支持个 gevent,star 数也不低,但是居然找不到官方文档,Orz
    NoAnyLove
        17
    NoAnyLove  
       2017-08-20 11:53:52 +08:00   1
    @Zioyi 建议你跑一跑代码,对比一下性能,记得反馈最终结果哦
    NoAnyLove
        18
    NoAnyLove  
       2017-08-20 12:05:16 +08:00   1
    @Zioyi Orz,突然反应过来,如果你的线程中不存在其他 I/O 操作,或者其他阻塞操作的话,按照之前的写法,你把 50 线程改成单线程,说不定会更快一些。。。。。。。 因为基本上对数据库的所有操作都放入临界区了。不过你之前既然说过 50 线程跑 14 分钟,单线程跑 40 分钟,那我只能推断你的线程中还存在了其他阻塞操作
    Zioyi
        19
    Zioyi  
    OP
       2017-08-21 12:22:57 +08:00
    没错,我的线程中还存在从文件中读取记录的 I/O 操作,基本代码如下:
    ```
    with open('recors.txt', 'rb') as rf:
    Zioyi
        20
    Zioyi  
    OP
       2017-08-21 12:33:51 +08:00
    @NoAnyLove 感谢。没错,我的线程中还存在从文件中读取记录的 I/O 操作,基本代码如下:
    ```
    ...
    with open(records1.txt', 'rb') as rf:
    record = rf.readline()
    while record:
    records.append(record)
    if len(records) == 500:
    currenct_insert_sql = function1(records) # records 列表存五百条 record 后做一次数据库 I/O
    if self.mysql_lock.acquire():
    cursor.execute(current_insert_sql)
    connection.commit()
    self.mysql_lock.release()
    records = []
    record = rf.readline()
    ...
    ```
    现在准备参考你的建议,尝试协程和更换 mysql 库,等测试出结果后会反馈出来。
    whx20202
        21
    whx20202  
       2017-08-23 15:17:49 +08:00
    我个人感觉那些 gevent 库,都是用 I/O 多路复用(系统层面)的原理,让开发通过同步方式进行异步(代码层面)的编程

    python 如果想要真正异步 IO 好像有个 pyaio,当然你的需求协程就能做

    如果有错误欢迎讨论
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     6127 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 01:49 PVG 09:49 LAX 18:49 JFK 21:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86