Ò»¡¢ÒýÑÔ
1. ´æ´¢Æ÷ɽ
´æ´¢Æ÷ɽÊÇ Randal Bryant ÔÚ¡¶ÉîÈëÀí½â¼ÆËã»úϵͳ¡·Ò»ÊéÖÐÌá³öµÄ¸ÅÄî¡£
»ùÓڳɱ¾¡¢Ð§ÂʵĿ¼Á¿£¬¼ÆËã»ú´æ´¢Æ÷±»Éè¼Æ³É¶à¼¶½ð×ÖËþ½á¹¹£¬Ëþ¶¥ÊÇËÙ¶È×î¿ì¡¢³É±¾×î¸ßµÄ
CPU ÄÚ²¿µÄ¼Ä´æÆ÷(Ò»°ã¼¸ KB)Óë¸ßËÙ»º´æ£¬Ëþµ×Êdzɱ¾×îµÍ¡¢ËÙ¶È×îÂýµÄ¹ãÓòÍøÔÆ´æ´¢(Èç°Ù¶ÈÔÆÃâ·Ñ
2T )

´æ´¢Æ÷ɽµÄÖ¸µ¼ÒâÒåÔÚÓÚ½ÒʾÁËÁ¼ºÃÉè¼Æ³ÌÐòµÄ±ØÒªÌõ¼þÊÇÐèÒªÓÐÓÅÐãµÄ¾Ö²¿ÐÔ£º
ʱ¼ä¾Ö²¿ÐÔ£ºÏàͬʱ¼äÄÚ£¬·ÃÎÊͬһµØÖ·´ÎÊýÔ½¶à£¬Ôòʱ¼ä¾Ö²¿ÐÔ±íÏÖÔ½¼Ñ;
¿Õ¼ä¾Ö²¿ÐÔ£ºÏÂÒ»´Î·ÃÎʵĴ洢Æ÷µØÖ·ÓëÉÏÒ»´ÎµÄ·ÃÎʹýµÄ´æ´¢Æ÷µØÖ·Î»ÖÃÁÚ½ü;
2. cpuµÄʱ¼ä¹Û

ÎÒÃǽ«Ò»¸öÆÕͨµÄ 2.6GHz µÄ CPU µÄÑÓ³Ùʱ¼ä·Å´óµ½ÈËÄÜÌåÑéµÄ³ß¶ÈÉÏ(Êý¾ÝÀ´×Ô΢ÐŹ«ÖںоÔ˵ÂëÊÂ)£ºÔÚ´æ´¢Æ÷¶¥²ãÖ´Ðе¥Ìõ¼Ä´æÆ÷Ö¸ÁîµÄʱ¼äΪ1ÃëÖÓ;´ÓµÚÎå²ã´ÅÅ̶Á
1MB Êý¾ÝÈ´ÐèÒªÒ»Äê°ë;ping ²»Í¬µÄ³ÇÓòÍøÖ÷»ú£¬ÍøÂç°üÐèÒª×ß 12.5 Äê¡£
Èç¹û³ÌÐò·¢ËÍÁËÒ»¸ö HTTP °üºó±ã×èÈûÔÚͬ²½µÈ´ýÏìÓ¦µÄ¹ý³ÌÉÏ£¬¼ÆËã»ú²»µÃ²»ÉµµÈ 12 ÄêºóµÄÄǸöÏìÓ¦ÔÙ´¦Àí±ðµÄÊÂÇ飬µÍϵÄÓ²¼þÀûÓÃÂʱØÈ»µ¼ÖµÍϵijÌÐòЧÂÊ¡£
3. ͬ²½±à³Ì
´ÓÒÔÉÏÊý¾Ý¿ÉÒÔ¿´³ö£¬ÄÚ´æÊý¾Ý¶Áд¡¢´ÅÅÌѰµÀ¶Áд¡¢Íø¿¨¶ÁдµÈ²Ù×÷¶¼ÊÇ I/O ²Ù×÷£¬Í¬²½³ÌÐòµÄÆ¿¾±ÔÚÓÚÂþ³¤µÄ
I/O µÈ´ý£¬ÏëÒªÌá¸ß³ÌÐòЧÂʱØÐë¼õÉÙ I/O µÈ´ýʱ¼ä£¬´ÓÌá¸ß³ÌÐòµÄ¾Ö²¿ÐÔ×ÅÊÖ¡£
ͬ²½±à³ÌµÄ¸Ä½ø·½Ê½ÓÐ¶à½ø³Ì¡¢¶àỊ̈߳¬µ«¶ÔÓÚ c10k ÎÊÌâ¶¼²»ÊÇÁ¼ºÃµÄ½â¾ö·½°¸£¬¶à½ø³ÌµÄ·½Ê½´æÔÚ²Ù×÷ϵͳ¿Éµ÷¶È½ø³ÌÊýÁ¿ÉÏÏ޽ϵͣ¬½ø³Ì¼äÉÏÏÂÎÄÇл»Ê±¼ä¹ý³¤£¬½ø³Ì¼äͨÐŽÏΪ¸´ÔÓ¡£
¶ø Python µÄ¶àÏ̷߳½Ê½£¬ÓÉÓÚ´æÔÚÖÚËùÖÜÖªµÄ GIL Ëø£¬ÐÔÄÜÌáÉý²¢²»Îȶ¨£¬½öÄÜÂú×ã³É°ÙÉÏǧ¹æÄ£µÄ
I/O Ãܼ¯ÐÍÈÎÎñ£¬¶àÏ̻߳¹ÓÐÒ»¸öȱµãÊÇÓɲÙ×÷ϵͳ½øÐÐÇÀռʽµ÷¶È´æÔÚ¾ºÌ¬Ìõ¼þ£¬¿ÉÄÜÐèÒªÒýÈëÁËËøÓë¶ÓÁеȱ£ÕÏÔ×ÓÐÔ²Ù×÷µÄ¹¤¾ß¡£
4. Òì²½±à³Ì
˵µ½Òì²½·Ç×èÈûµ÷Óã¬Ä¿Ç°µÄ´úÃû´Ê¶¼ÊÇ epoll Óë kqueue£¬select/poll ÓÉÓÚЧÂÊÎÊÌâ»ù±¾Òѱ»È¡´ú¡£
epoll ÊÇ04Äê Linux2.6 ÒýÈëÄں˵ÄÒ»ÖÖ I/O ʼþ֪ͨ»úÖÆ£¬ËüµÄ×÷ÓÃÊǽ«´óÁ¿µÄÎļþÃèÊö·ûÍйܸøÄںˣ¬Äں˽«×îµ×²ãµÄ
I/O ״̬±ä»¯·â×°³É¶Áдʼþ£¬ÕâÑù¾Í±ÜÃâÁËÓɳÌÐòԱȥÖ÷¶¯ÂÖѯ״̬±ä»¯µÄÖØ¸´¹¤×÷£¬³ÌÐòÔ±½«»Øµ÷º¯Êý×¢²áµ½
epoll µÄ״̬ÉÏ£¬µ±¼ì²âµ½Ïà¶ÔÓ¦ÎļþÃèÊö·û²úÉú״̬±ä»¯Ê±£¬¾Í½øÐк¯Êý»Øµ÷¡£
ʼþÑ»·ÊÇÒì²½±à³ÌµÄµ×²ã»ùʯ¡£

ÉÏͼÊǼòµ¥µÄEventLoopµÄʵÏÖÔÀí£¬
1.Óû§´´½¨ÁËÁ½¸ösocketÁ¬½Ó£¬½«ÏµÍ³·µ»ØµÄÁ½¸öÎļþÃèÊö·ûfd3¡¢fd4ͨ¹ýϵͳµ÷ÓÃÔÚepollÉÏ×¢²á¶Áдʼþ;
2.µ±Íø¿¨½âÎöµ½Ò»¸ötcp°üʱ£¬Äں˸ù¾ÝÎåÔª×éÕÒµ½ÏàÓ¦µ½ÎļþÃèÊö·û£¬×Ô¶¯´¥·¢Æä¶ÔÓ¦µÄ¾ÍÐ÷ʼþ״̬£¬²¢½«¸ÃÎļþÃèÊö·ûÌí¼Óµ½¾ÍÐ÷Á´±íÖС£
3.³ÌÐòµ÷ÓÃepoll.poll()£¬·µ»Ø¿É¶ÁдµÄʼþ¼¯ºÏ¡£
4.¶Ôʼþ¼¯ºÏ½øÐÐÂÖѯ£¬µ÷Óûص÷º¯ÊýµÈ
5.Ò»ÂÖʼþÑ»·½áÊø£¬Ñ»·Íù¸´¡£
epoll ²¢·ÇÒøµ¯£¬´ÓͼÖпÉÒԹ۲쵽£¬Èç¹ûÓû§¹Ø×¢µÄ²ã´ÎºÜµÍ£¬Ö±½Ó²Ù×÷epollÈ¥¹¹Ôìά»¤Ê¼þµÄÑ»·£¬´Óµ×²ãµ½¸ß²ãµÄÒµÎñÂß¼ÐèÒª²ã²ã»Øµ÷£¬Ôì³Écallback
hell£¬²¢ÇҿɶÁÐԽϲËùÒÔ£¬Õâ¸ö·±ËöµÄ×¢²á»Øµ÷Óë»Øµ÷µÄ¹ý³ÌµÃÒÔ·â×°£¬²¢³éÏó³ÉEventLoop¡£EventLoopÆÁ±ÎÁ˽øÐÐepollϵͳµ÷ÓõľßÌå²Ù×÷¡£¶ÔÓÚÓû§À´Ëµ£¬½«²»Í¬µÄI/O״̬¿¼Á¿ÎªÊ¼þµÄ´¥·¢£¬Ö»Ðè¹Ø×¢¸ü¸ß²ã´Îϲ»Í¬Ê¼þµÄ»Øµ÷ÐÐΪ¡£ÖîÈçlibev,
libeventÖ®ÀàµÄʹÓÃC±àдµÄ¸ßÐÔÄÜÒ첽ʼþ¿âÒѾȡ´úÕⲿ·ÖËöËéµÄ¹¤×÷¡£
ÔÚPython¿ò¼ÜÀïÒ»°ã»á¼ûµ½µÄÕ⼸ÖÖʼþÑ»·£º
1.libevent/libev: Gevent(greenlet+ǰÆÚlibevent£¬ºóÆÚlibev)ʹÓõÄÍøÂç¿â£¬¹ã·ºÓ¦ÓÃ;
2.tornado: tornado¿ò¼Ü×Ô¼ºÊµÏÖµÄIOLOOP;
3.picoev: meinheld(greenlet+picoev)ʹÓõÄÍøÂç¿â£¬Ð¡ÇÉÇáÁ¿£¬Ïà½ÏÓÚlibeventÔÚÊý¾Ý½á¹¹ºÍʼþ¼ì²âÄ£ÐÍÉÏ×öÁ˸Ľø£¬ËùÒÔËٶȸü¿ì¡£µ«´Ógithub¿´ÆðÀ´ÒѾÄê¾ÃʧÐÞ£¬ÓõÄÈ˲»¶à¡£
4.uvloop: Python3ʱ´úµÄÐÂÆðÖ®Ðã¡£Guido²Ùµ¶´òÔìÁËasyncio¿â£¬asyncio¿ÉÒÔÅäÖÿɲå°ÎµÄevent
loop£¬µ«ÐèÒªÂú×ãÏà¹ØµÄAPIÒªÇó£¬uvloop¼Ì³Ð×Ôlibuv£¬½«Ò»Ð©µÍ²ãµÄ½á¹¹ÌåºÍº¯ÊýÓÃPython¶ÔÏó°ü×°¡£Ä¿Ç°Sanic¿ò¼Ü»ùÓÚÕâ¸ö¿â
5. гÌ
EventLoop¼ò»¯Á˲»Í¬Æ½Ì¨ÉϵÄʼþ´¦Àí£¬µ«ÊÇ´¦Àíʼþ´¥·¢Ê±µÄ»Øµ÷ÒÀÈ»ºÜÂé·³£¬ÏìӦʽµÄÒì²½³ÌÐò±àд¶Ô³ÌÐòÔ±µÄÐÄÖÇÊÇÒ»ÏСµÄÂé·³¡£
Òò´Ë£¬Ð³Ì±»ÒýÈëÀ´Ìæ´ú»Øµ÷ÒÔ¼ò»¯ÎÊÌ⡣гÌÄ£ÐÍÖ÷ÒªÔÚÔÚÒÔÏ·½ÃæÓÅÓڻص÷Ä£ÐÍ£º
ÒÔ½üËÆÍ¬²½´úÂëµÄ±à³Ìģʽȡ´úÒì²½»Øµ÷ģʽ£¬ÕæÊµµÄÒµÎñÂß¼ÍùÍùÊÇͬ²½ÏßÐÔÍÆÑݵģ¬Òò´Ë£¬ÕâÖÖͬ²½Ê½µÄ´úÂëдÆðÀ´¸ü¼ÓÈÝÒס£µ×²ãµÄ»Øµ÷ÒÀÈ»ÊÇcallback
hell£¬µ«Õⲿ·ÖÔà»îÀÛ»îÒѾת½»¸ø±àÒëÆ÷Óë½âÊÍÆ÷È¥Íê³É£¬³ÌÐòÔ±²»Ò׳ö´í¡£
Òì³£´¦Àí¸ü¼Ó½¡È«£¬¿ÉÒÔ¸´ÓÃÓïÑÔÄڵĴíÎó´¦Àí»úÖÆ£¬»Øµ÷·½Ê½¡£¶ø´«Í³Òì²½»Øµ÷ģʽÐèÒª×Ô¼ºÅж¨³É¹¦Ê§°Ü£¬´íÎó´¦ÀíÐÐΪ¸´ÔÓ»¯¡£
ÉÏÏÂÎĹÜÀí¼òµ¥»¯£¬»Øµ÷·½Ê½´úÂëÉÏÏÂÎĹÜÀíÑÏÖØÒÀÀµ±Õ°ü£¬²»Í¬µÄ»Øµ÷º¯ÊýÖ®¼äÏ໥ñîºÏ£¬¸îÁÑÁËÏàͬµÄÉÏÏÂÎÄ´¦ÀíÂß¼¡£Ð³ÌÖ±½ÓÀûÓôúÂëµÄÖ´ÐÐλÖÃÀ´±íʾ״̬£¬¶ø»Øµ÷ÔòÊÇά»¤ÁËÒ»¶ÑÊý¾Ý½á¹¹À´´¦Àí״̬¡£
·½±ã´¦Àí²¢·¢ÐÐΪ£¬Ð³ÌµÄ¿ªÏú³É±¾ºÜµÍ£¬Ã¿Ò»¸öг̽öÓÐÒ»¸öÇáÇɵÄÓû§Ì¬Õ»¿Õ¼ä¡£
6. EventLoopÓëг̵ķ¢Õ¹Ê·
04Ä꣬event-driven µÄ nginx µ®Éú²¢¿ìËÙ´«²¥£¬06ÄêÒÔºó´Ó¶íÓïÇø¹ú¼ÒÀ©É¢µ½È«Çò¡£Í¬Ê±ÆÚ£¬EventLoop
±äµÃ¾ßÏó»¯Óë¶àÔª»¯£¬Ïà¼ÌÔÚ²»Í¬µÄ±à³ÌÓïÑÔʵÏÖ¡£
½üÊ®ÄêÒÔÀ´£¬ºó¶ËÁìÓòÄÚ¹ÅÀϵÄ×ÓÀý³ÌÓëʼþÑ»·µÃµ½½áºÏ£¬Ð³Ì(Ð×÷ʽ×ÓÀý³Ì)¿ìËÙ·¢Õ¹£¬²¢Ò²¸ïÐÂÓëµ®ÉúÁËһЩÓïÑÔ£¬±ÈÈç
golang µÄ goroutine£¬luajit µÄ coroutine£¬Python µÄ gevent,erlang
µÄ process£¬scala µÄ actor µÈ¡£
¾Í²»Í¬ÓïÑÔÖÐÃæÏò²¢·¢Éè¼ÆµÄгÌʵÏÖ¶øÑÔ£¬Scala Óë Erlang µÄ Actor Ä£ÐÍ¡¢Golang
ÖÐµÄ goroutine ¶¼½Ï Python ¸üΪ³ÉÊ죬²»Í¬µÄгÌʹÓÃͨÐÅÀ´¹²ÏíÄڴ棬ÓÅ»¯Á˾ºÌ¬¡¢³åÍ»¡¢²»Ò»ÖÂÐÔµÈÎÊÌ⡣Ȼ¶ø£¬¸ù±¾µÄÀíÄîûÓÐÇø±ð£¬¶¼ÊÇÔÚÓû§Ì¬Í¨¹ýʼþÑ»·Çý¶¯ÊµÏÖµ÷¶È¡£
ÓÉÓÚÀúÊ·°ü¸¤½ÏÉÙ£¬ºó¶ËÓïÑÔÉϵĸ÷ÖÖÒì²½¼¼Êõ³ý Python Twisted Íâ»ù±¾Ò²Ã»ÓÐ callback
hell µÄ´æÔÚ¡£ÆäËûµÄ·½°¸¶¼ÒѾ½« callback hell µÄ¹ý³Ì½øÐзâ×°£¬½»¸ø¿â´úÂë¡¢±àÒëÆ÷¡¢½âÊÍÆ÷È¥½â¾ö¡£
ÓÐÁËг̣¬ÓÐÁËʼþÑ»·¿â£¬´«Í³µÄ C10K ÎÊÌâÒѾ²»ÊÇÌôÕ½²¢ÒѾÉÏÉýµ½ÁË C1M ÎÊÌâ¡£
¶þ¡¢Gevent
Python2 ʱ´úµÄг̼¼ÊõÖ÷ÒªÊÇ Gevent£¬ÁíÒ»¸ö meinheld ±È½ÏСÖÚ¡£Gevent
ÓаýÓбᣬ¸ºÃæ¹ÛµãÈÏΪËüµÄʵÏÖ²»¹» Pythonic£¬ÍÑÀë½âÊÍÆ÷¶À×ÔʵÏÖÁ˺ںеĵ÷¶ÈÆ÷£¬monkey
patch Èò»Á˽âµÄÓû§²úÉú»ìÏý¡£ÕýÃæ¹ÛµãÈÏΪÕýÊÇÕâÑù²ÅµÃÒÔÆÁ±ÎËùÓеÄϸ½Ú£¬¼ò»¯Ê¹ÓÃÄѶȡ£
Gevent »ùÓÚ Greenlet Óë Libev£¬greenlet ÊÇÒ»ÖÖ΢Ï̻߳òÕßг̣¬ÔÚµ÷¶ÈÁ£¶ÈÉϱÈ
PY3 µÄг̸ü´ó¡£greenlet ´æÔÚÓÚÏß³ÌÈÝÆ÷ÖУ¬ÆäÐÐΪÀàËÆỊ̈߳¬ÓÐ×Ô¼º¶ÀÁ¢µÄÕ»¿Õ¼ä£¬²»Í¬µÄ
greenlet µÄÇл»ÀàËÆ²Ù×÷ϵͳ²ãµÄÏß³ÌÇл»¡£
greenlet.hub Ò²ÊÇÒ»¸ö¼Ì³ÐÓÚÔÉú greenlet µÄ¶ÔÏó£¬Ò²ÊÇÆäËû greenlet
µÄ¸¸½Úµã£¬ËüÖ÷Òª¸ºÔðÈÎÎñµ÷¶È¡£µ±Ò»¸ö greenlet гÌÖ´ÐÐÍ겿·ÖÀý³Ìºóµ½´ï¶Ïµã£¬Í¨¹ý greenlet.switch()
ÏòÉÏת½»¿ØÖÆÈ¨¸ø hub ¶ÔÏó£¬hub Ö´ÐÐÉÏÏÂÎÄÇл»µÄ²Ù×÷£º´Ó¼Ä´æÆ÷¡¢¸ßËÙ»º´æÖб¸·Ýµ±Ç° greenlet
µÄÕ»ÄÚÈݵ½ÄÚ´æÖУ¬²¢½«ÔÀ´±¸·ÝµÄÁíÒ»¸ö greenlet Õ»Êý¾Ý»Ö¸´µ½¼Ä´æÆ÷ÖС£
hub ¶ÔÏóÄÚ·â×°ÁËÒ»¸ö loop ¶ÔÏó£¬loop ¸ºÔð·â×° libev µÄÏà¹Ø²Ù×÷²¢ÏòÉÏÌṩ½Ó¿Ú£¬ËùÓÐ
greenlet ÔÚͨ¹ý loop Çý¶¯µÄ hub ϱ»µ÷¶È¡£
Èý¡¢´Óyieldµ½async/await
1. Éú³ÉÆ÷µÄ½ø»¯
ÔÚ Python2.2 ÖУ¬µÚÒ»´ÎÒýÈëÁËÉú³ÉÆ÷£¬Éú³ÉÆ÷ʵÏÖÁËÒ»ÖÖ¶èÐÔ¡¢¶à´ÎȡֵµÄ·½·¨£¬´Ëʱ»¹ÊÇͨ¹ý
next ¹¹ÔìÉú³Éµü´úÁ´»ò next ½øÐжà´Îȡֵ¡£
Ö±µ½ÔÚ Python2.5 ÖУ¬yield ¹Ø¼ü×Ö±»¼ÓÈëµ½Óï·¨ÖУ¬Õâʱ£¬Éú³ÉÆ÷ÓÐÁ˼ÇÒ书ÄÜ£¬ÏÂÒ»´Î´ÓÉú³ÉÆ÷ÖÐȡֵ¿ÉÒÔ»Ö¸´µ½Éú³ÉÆ÷ÉÏ´Î
yield Ö´ÐеÄλÖá£
֮ǰµÄÉú³ÉÆ÷¶¼ÊǹØÓÚÈçºÎ¹¹Ôìµü´úÆ÷£¬ÔÚ Python2.5 ÖÐÉú³ÉÆ÷»¹¼ÓÈëÁË send ·½·¨£¬Óë yield
´îÅäʹÓá£
ÎÒÃÇ·¢ÏÖ£¬´Ëʱ£¬Éú³ÉÆ÷²»½ö½ö¿ÉÒÔ yield ÔÝÍ£µ½Ò»¸ö״̬£¬»¹¿ÉÒÔÍùËüÍ£Ö¹µÄλÖÃͨ¹ý send ·½·¨´«ÈëÒ»¸öÖµ¸Ä±äÆä״̬¡£
¾ÙÒ»¸ö¼òµ¥µÄʾÀý£¬Ö÷ÒªÊìϤ yield Óë send ÓëÍâ½çµÄ½»»¥Á÷³Ì£º
def
jump_range(up_to):
step = 0
while step < up_to:
jump = yield step
print("jump", jump)
if jump is None:
jump = 1
step += jump
print("step", step)
if __name__ == '__main__':
iterator = jump_range(10)
print(next(iterator)) # 0
print(iterator.send(4)) # jump4; step4; 4
print(next(iterator)) # jump None; step5; 5
print(iterator.send(-1)) # jump -1; step4; 4
|
ÔÚ Python3.3 ÖУ¬Éú³ÉÆ÷ÓÖÒýÈëÁË yield from
¹Ø¼ü×Ö£¬yield from ʵÏÖÁËÔÚÉú³ÉÆ÷ÄÚµ÷ÓÃÁíÍâÉú³ÉÆ÷µÄ¹¦ÄÜ£¬¿ÉÒÔÇáÒ×µÄÖØ¹¹Éú³ÉÆ÷£¬±ÈÈ罫¶à¸öÉú³ÉÆ÷Á¬½ÓÔÚÒ»ÆðÖ´ÐС£
def
gen_3():
yield 3
def gen_234():
yield 2
yield from gen_3()
yield 4
def main():
yield 1
yield from gen_234()
yield 5
for element in main():
print(element) # 1,2,3,4,5 |

´ÓͼÖпÉÒÔ¿´³ö yield from µÄÌØµã¡£Ê¹Óà itertools.chain ¿ÉÒÔÒÔÉú³ÉÆ÷Ϊ×îС×éºÏ×Ó½øÐÐÁ´Ê½×éºÏ£¬Ê¹ÓÃ
itertools.cycle ¿ÉÒÔ¶Ôµ¥¶ÀÒ»¸öÉú³ÉÆ÷Ê×βÏà½Ó£¬¹¹ÔìÒ»¸öÑ»·Á´¡£
ʹÓà yield from ʱ¿ÉÒÔÔÚÉú³ÉÆ÷ÖÐ´ÓÆäËûÉú³ÉÆ÷ yield Ò»¸öÖµ£¬ÕâÑù²»Í¬µÄÉú³ÉÆ÷Ö®¼ä¿ÉÒÔ»¥ÏàͨÐÅ£¬ÕâÑù¹¹Ôì³öµÄÉú³ÉÁ´¸ü¼Ó¸´ÔÓ£¬µ«Éú³ÉÁ´×îС×éºÏ×ÓµÄÁ£¶ÈÈ´¾«Ï¸ÖÁµ¥¸ö
yield ¶ÔÏó¡£
2. ¶ÌÔݵÄasynico.coroutine Óëyield from
ÓÐÁËPython3.3ÖÐÒýÈëµÄyield from ÕâÏ¾ß£¬Python3.4 ÖÐмÓÈëÁËasyncio¿â£¬²¢ÌṩÁËÒ»¸öĬÈϵÄevent
loop¡£Python3.4ÓÐÁË×ã¹»µÄ»ù´¡¹¤¾ß½øÐÐÒì²½²¢·¢±à³Ì¡£
²¢·¢±à³ÌͬʱִÐжàÌõ¶ÀÁ¢µÄÂß¼Á÷£¬Ã¿¸öг̶¼ÓжÀÁ¢µÄÕ»¿Õ¼ä£¬¼´Ê¹ËüÃÇÊǶ¼¹¤×÷ÔÚͬ¸öÏß³ÌÖеġ£ÒÔÏÂÊÇÒ»¸öʾÀý´úÂ룺
import
asyncio
import aiohttp
@asyncio.coroutine
def fetch_page(session, url):
response = yield from session.get(url)
if response.status == 200:
text = yield from response.text()
print(text)
loop = asyncio.get_event_loop()
session = aiohttp.ClientSession(looploop=loop)
tasks = [
asyncio.ensure_future(
fetch_page(session, "http://bigsec.com/products/redq/")),
asyncio.ensure_future(
fetch_page(session, "http://bigsec.com/products/warden/"))
]
loop.run_until_complete(asyncio.wait(tasks))
session.close()
loop.close() |
ÔÚ Python3.4 ÖУ¬asyncio.coroutine ×°ÊÎÆ÷ÊÇÓÃÀ´½«º¯Êýת»»ÎªÐ³ÌµÄÓï·¨£¬ÕâÒ²ÊÇ
Python µÚÒ»´ÎÌṩµÄÉú³ÉÆ÷Ð³Ì ¡£Ö»ÓÐͨ¹ý¸Ã×°ÊÎÆ÷£¬Éú³ÉÆ÷²ÅÄÜʵÏÖг̽ӿڡ£Ê¹ÓÃгÌʱ£¬ÄãÐèҪʹÓÃ
yield from ¹Ø¼ü×Ö½«Ò»¸ö asyncio.Future ¶ÔÏóÏòÏ´«µÝ¸øÊ¼þÑ»·£¬µ±Õâ¸ö Future
¶ÔÏó»¹Î´¾ÍÐ÷ʱ£¬¸Ãг̾ÍÔÝʱ¹ÒÆðÒÔ´¦ÀíÆäËûÈÎÎñ¡£Ò»µ© Future ¶ÔÏóÍê³É£¬Ê¼þÑ»·½«»áÕì²âµ½×´Ì¬±ä»¯£¬»á½«
Future ¶ÔÏóµÄ½á¹ûͨ¹ý send ·½·¨·½·¨·µ»Ø¸øÉú³ÉÆ÷г̣¬È»ºóÉú³ÉÆ÷»Ö¸´¹¤×÷¡£
ÔÚÒÔÉϵÄʾÀý´úÂëÖУ¬Ê×ÏÈʵÀý»¯Ò»¸ö eventloop£¬²¢½«Æä´«µÝ¸ø aiohttp.ClientSession
ʹÓã¬ÕâÑù session ¾Í²»Óô´½¨×Ô¼ºµÄʼþÑ»·¡£
´Ë´¦ÏÔʽµÄ´´½¨ÁËÁ½¸öÈÎÎñ£¬Ö»Óе± fetch_page È¡µÃ api.bigsec.com Á½¸ö url
µÄÊý¾Ý²¢´òÓ¡Íê³Éºó£¬ËùÓÐÈÎÎñ²ÅÄܽáÊø£¬È»ºó¹Ø±Õ session Óë loop£¬ÊÍ·ÅÁ¬½Ó×ÊÔ´¡£
µ±´úÂëÔËÐе½ response = yield from session.get(url)´¦£¬fetch_page
г̱»¹ÒÆð£¬ÒþʽµÄ½«Ò»¸ö Future ¶ÔÏ󴫵ݸøÊ¼þÑ»·£¬Ö»Óе± session.get() Íê³Éºó£¬¸ÃÈÎÎñ²ÅËãÍê³É¡£
session.get() ÄÚ²¿Ò²ÊÇг̣¬ÆäÊý¾Ý´«ÊäλÓÚÔÚ´æ´¢Æ÷ɽ×îÂýµÄÍøÂç²ã¡£µ± session.get
Íê³Éʱ£¬È¡µÃÁËÒ»¸ö response ¶ÔÏó£¬ÔÙ´«µÝ¸øÔÀ´µÄ fetch_page Éú³ÉÆ÷г̣¬»Ö¸´Æä¹¤×÷״̬¡£
ΪÁËÌá¸ßËÙ¶È£¬´Ë´¦ get ·½·¨½«È¡µÃ http header Óë body ·Ö½â³ÉÁ½´ÎÈÎÎñ£¬¼õÉÙÒ»´ÎÐÔ´«ÊäµÄÊý¾ÝÁ¿¡£response.text()
¼´ÊÇÒì²½ÇëÇó http body¡£
ʹÓà dis ¿â²é¿´ fetch_page г̵Ä×Ö½ÚÂ룬GET_YIELD_FROM_ITER ÊÇ
yield from µÄ²Ù×÷Âë:
In
[4]: import dis
In [5]: dis.dis(fetch_page)
0 LOAD_FAST 0 (session)
2 LOAD_ATTR 0 (get)
4 LOAD_FAST 1 (url)
6 CALL_FUNCTION 1
8 GET_YIELD_FROM_ITER
10 LOAD_CONST 0 (None)
12 YIELD_FROM
14 STORE_FAST 2 (response)
16 LOAD_FAST 2 (response)
18 LOAD_ATTR 1 (status)
20 LOAD_CONST 1 (200)
22 COMPARE_OP 2 (==)
24 POP_JUMP_IF_FALSE 48
26 LOAD_FAST 2 (response)
28 LOAD_ATTR 2 (text)
30 CALL_FUNCTION 0
32 GET_YIELD_FROM_ITER
34 LOAD_CONST 0 (None)
36 YIELD_FROM
38 STORE_FAST 3 (text)
40 LOAD_GLOBAL 3 (print)
42 LOAD_FAST 3 (text)
44 CALL_FUNCTION 1
46 POP_TOP
>> 48 LOAD_CONST 0 (None)
50 RETURN_VALUE |
3. asyncÓë await¹Ø¼ü×Ö
Python3.5 ÖÐÒýÈëÁËÕâÁ½¸ö¹Ø¼ü×ÖÓÃÒÔÈ¡´ú asyncio.coroutine Óë yield
from£¬´ÓÓïÒåÉ϶¨ÒåÁËÔÉúг̹ؼü×Ö£¬±ÜÃâÁËʹÓÃÕß¶ÔÉú³ÉÆ÷гÌÓëÉú³ÉÆ÷µÄ»ìÏý¡£Õâ¸ö½×¶Î(3.0-3.4)ʹÓÃ
Python µÄÈ˲»¶à£¬Òò´ËÀúÊ·°ü¸¤²»ÖØ£¬¿ÉÒÔ½øÐÐһЩ½Ï´óµÄ¸ïС£
await µÄÐÐΪÀàËÆ yield from£¬µ«ÊÇËüÃÇÒì²½µÈ´ýµÄ¶ÔÏó²¢²»Ò»Ö£¬yield from
µÈ´ýµÄÊÇÒ»¸öÉú³ÉÆ÷¶ÔÏ󣬶øawait½ÓÊÕµÄÊǶ¨ÒåÁË__await__·½·¨µÄ awaitable ¶ÔÏó¡£
ÔÚ Python ÖУ¬Ð³ÌÒ²ÊÇ awaitable ¶ÔÏó£¬collections.abc.Coroutine
¶ÔÏó¼Ì³Ð×Ô collections.abc.Awaitable¡£
Òò´Ë£¬½«ÉÏһС½ÚµÄʾÀý´úÂë¸Äд³É£º
import
asyncio
import aiohttp
async def fetch_page(session, url):
response = await session.get(url)
if response.status == 200:
text = await response.text()
print(text)
loop = asyncio.get_event_loop()
session = aiohttp.ClientSession(looploop=loop)
tasks = [
asyncio.ensure_future(
fetch_page(session, "http://bigsec.com/products/redq/")),
asyncio.ensure_future(
fetch_page(session, "http://bigsec.com/products/warden/"))
]
loop.run_until_complete(asyncio.wait(tasks))
session.close()
loop.close() |
´Ó Python ÓïÑÔ·¢Õ¹µÄ½Ç¶ÈÀ´Ëµ£¬async/await ²¢·ÇÊǶàôΰ´óµÄ¸Ä½ø£¬Ö»ÊÇÒý½øÁËÆäËûÓïÑÔÖгÉÊìµÄÓïÒ壬г̵Ļùʯ»¹ÊÇÔÚÓÚ
eventloop ¿âµÄ·¢Õ¹£¬ÒÔ¼°Éú³ÉÆ÷µÄÍêÉÆ¡£´Ó½á¹¹ÔÀí¶øÑÔ£¬asyncio ʵÖʵ£µ±µÄ½ÇÉ«ÊÇÒ»¸öÒì²½¿ò¼Ü£¬async/await
ÊÇΪÒì²½¿ò¼ÜÌṩµÄ API£¬ÒòΪʹÓÃÕßĿǰ²¢²»ÄÜÍÑÀë asyncio »òÆäËûÒì²½¿âʹÓà async/await
±àдг̴úÂë¡£¼´Ê¹Óû§¿ÉÒÔ±ÜÃâÏÔʽµØÊµÀý»¯Ê¼þÑ»·£¬±ÈÈçÖ§³Ö asyncio/await Óï·¨µÄгÌÍøÂç¿â
curio£¬µ«ÊÇÍÑÀëÁË eventloop ÈçÐÄÔà°ãµÄÇý¶¯×÷Óã¬async/await ¹Ø¼ü×Ö±¾ÉíÒ²ºÁÎÞ×÷Óá£
ËÄ¡¢async/awaitµÄʹÓÃ

1. Future
²»Óûص÷·½·¨±àдÒì²½´úÂëºó£¬ÎªÁË»ñÈ¡Òì²½µ÷ÓõĽá¹û£¬ÒýÈëÒ»¸ö Future δÀ´¶ÔÏó¡£Future
·â×°ÁËÓë loop µÄ½»»¥ÐÐΪ£¬add_done_callback ·½·¨Ïò epoll ×¢²á»Øµ÷º¯Êý£¬µ±
result ÊôÐԵõ½·µ»ØÖµºó£¬»áÔËÐÐ֮ǰע²áµÄ»Øµ÷º¯Êý£¬ÏòÉÏ´«µÝ¸ø coroutine¡£µ«ÊÇ£¬Ã¿Ò»¸ö½ÇÉ«¸÷ÓÐ×Ô¼ºµÄÖ°Ôð£¬ÓÃ
Future ÏòÉú³ÉÆ÷ send result ÒÔ»Ö¸´¹¤×÷״̬²¢²»ºÏÊÊ£¬Future ¶ÔÏó±¾ÉíµÄÉú´æÖÜÆÚ±È½Ï¶Ì£¬Ã¿Ò»´Î×¢²á»Øµ÷¡¢²úÉúʼþ¡¢´¥·¢»Øµ÷¹ý³Ìºó¹¤×÷ÒѾÍê³É¡£ËùÒÔÕâÀïÓÖÐèÒªÔÚÉú³ÉÆ÷гÌÓë
Future ¶ÔÏóÖÐÒýÈëÒ»¸öеĶÔÏó Task£¬¶ÔÉú³ÉÆ÷г̽øÐÐ״̬¹ÜÀí¡£
2. Task
Task£¬¹ËÃû˼Ò壬ÊÇά»¤Éú³ÉÆ÷гÌ״̬´¦ÀíÖ´ÐÐÂß¼µÄµÄÈÎÎñ£¬Task ÄÚµÄ_step ·½·¨¸ºÔðÉú³ÉÆ÷гÌÓë
EventLoop ½»»¥¹ý³ÌµÄ×´Ì¬Ç¨ÒÆ:ÏòÐ³Ì send Ò»¸öÖµ£¬»Ö¸´Æä¹¤×÷״̬£¬Ð³ÌÔËÐе½¶Ïµãºó£¬µÃµ½ÐµÄδÀ´¶ÔÏó£¬ÔÙ´¦Àí
future Óë loop µÄ»Øµ÷×¢²á¹ý³Ì¡£
3. Loop
ʼþÑ»·µÄ¹¤×÷·½Ê½ÓëÓû§ÉèÏë´æÔÚһЩƫ²î£¬ÀíËùµ±È»µÄÈÏÖªÓ¦ÊÇÿ¸öÏ̶߳¼¿ÉÒÔÓÐÒ»¸ö¶ÀÁ¢µÄ loop¡£µ«ÊÇÔÚÔËÐÐÖУ¬ÔÚÖ÷Ïß³ÌÖвÅÄÜͨ¹ý
asyncio.get_event_loop() ´´½¨Ò»¸öÐ嵀 loop£¬¶øÔÚÆäËûÏß³Ìʱ£¬Ê¹Óà get_event_loop()
È´»áÅ×´í£¬ÕýÈ·µÄ×ö·¨Ó¦¸ÃÊÇ asyncio.set_event_loop() ½øÐе±Ç°Ïß³ÌÓë loop
µÄÏÔʽ°ó¶¨¡£ÓÉÓÚ loop µÄÔË×÷ÐÐΪ²¢²»ÊÜ Python ´úÂëµÄ¿ØÖÆ£¬ËùÒÔÎÞ·¨Îȶ¨µÄ½«Ð³ÌÍØÕ¹µ½¶àÏß³ÌÖÐÔËÐС£
гÌÔÚ¹¤×÷ʱ£¬²¢²»Á˽âÊÇÄĸö loop ÔÚ¶ÔÆäµ÷¶È£¬¼´Ê¹µ÷Óà asyncio.get_event_loop()
Ò²²»Ò»¶¨ÄÜ»ñÈ¡µ½ÕæÕýÔËÐеÄÄǸö loop¡£Òò´ËÔÚ¸÷ÖÖ¿â´úÂëÖУ¬ÊµÀý»¯¶ÔÏóʱ¶¼±ØÐëÏÔʽµÄ´«µÝµ±Ç°µÄ loop
ÒÔ½øÐа󶨡£
4. ÁíÒ»¸öFuture
Python ÀïÁíÒ»¸ö Future ¶ÔÏóÊÇ concurrent.futures.Future£¬Óë
asyncio.Future »¥²»¼æÈÝ£¬µ«ÈÝÒײúÉú»ìÏý¡£concurrent.futures ÊÇÏ̼߳¶µÄ
Future ¶ÔÏ󣬵±Ê¹Óà concurrent.futures.Executor ½øÐжàÏ̱߳à³ÌʱÓÃÓÚÔÚ²»Í¬µÄ
thread Ö®¼ä´«µÝ½á¹û¡£
5. ÏÖ½×¶ÎasyncioÉú̬·¢Õ¹µÄÀ§ÄÑ
ÓÉÓÚÕâÁ½¸ö¹Ø¼ü×ÖÔÚ2014Äê·¢²¼µÄPython3.5Öвű»ÒýÈ룬·¢Õ¹ÀúÊ·½Ï¶Ì£¬ÔÚPython2ÓëPython3¸îÁѵĴ󻷾³Ï£¬Éú̬»·¾³µÄ½¨Á¢²¢²»ÍêÉÆ;
¶ÔÓÚʹÓÃÕßÀ´Ëµ£¬Ï£ÍûµÄÂß¼ÊÇÒýÈëÒ»¸ö¿âÈ»ºóµ÷Óò¢»ñÈ¡½á¹û£¬²¢²»¹ØÐĵÚÈý·½¿âµÄÄÚ²¿Âß¼¡£È»¶øÊ¹ÓÃг̱àдÒì²½´úÂëʱÐèÒª´¦ÀíÓëʼþÑ»·µÄ½»»¥¡£¶ÔÓÚÒì²½¿âÀ´Ëµ£¬Æä¶ÔÍâ·â×°ÐÔ²¢²»Äܴﵽͬ²½¿âÄÇô¸ß¡£Òì²½±à³Ìʱ£¬Óû§Í¨³£Ö»»áÑ¡ÔñÒ»¸öµÚÈý·½¿âÀ´´¦ÀíËùÓÐHTTPÂß¼¡£µ«ÊDz»Í¬µÄÒ첽ʵÏÖ·½·¨²»Ò»Ö£¬»¥²»¼æÈÝ£¬·ÖÆç×è°ÁËÉçÇø×³´ó;
Òì²½´úÂëËäÈ»¿ì£¬µ«²»ÄÜ×èÈû£¬Ò»µ©×èÈûÕû¸ö³ÌÐòʧЧ¡£Ê¹ÓöàÏ̻߳ò¶à½ø³ÌµÄ·½Ê½½«µ÷¶ÈȨ½»¸ø²Ù×÷ϵͳ£¬Î´Ãâ²»ÊÇÒ»ÖÖ×ÔÎÒ±£»¤;
6. һЩ¸öÈË¿´·¨
Æäʵ˵ÁËÕâô¶à£¬¸öÈ˾õµÃ asyncio ËäÈ»¸ü¼ÓÓÅÑÅ£¬È´Êµ¼ÊʹÓÃÉϲ¢²»ÊÇÏñ±íÃæ¿´ÆðÀ´µÄÄÇôÃÀºÃ¡£Ê×ÏÈ£¬Ëü²»ÊÇÌØ±ðµÄ¿ì(¾Ý˵±È
gevent ¿ìÒ»±¶)£¬È´ÒýÈëÁ˸ü¶àµÄ¸´ÔÓÐÔ£¬¶øÇÒ´Ó´íÎóÐÅÏ¢ debug ¸ü¼ÓÀ§ÄÑ¡£Æä´Î£¬ÕâÌ×½â¾ö·½°¸²¢²»³ÉÊ죬×î½ü
3.4¡¢3.5¡¢3.6 µÄÈý¸ö°æ±¾£¬Ð³ÌÒ²Óи÷ÖÖµÄϸ½Ú±ä»¯£¬Ò²±äµÃÔ½À´Ô½¸´ÔÓ£¬³ÌÐòÔ±±ØÐëËæÊ±¹Ø×¢ÓïÑԵı仯²ÅÄÜͬ²½¡£ÁîÈËÒÉ»óµÄÊÇΪʲô
Python Ò»¶¨Òª¼á³ÖÓÃÉú³ÉÆ÷À´ÊµÏÖг̣¬×îºóÓÖ½«Éú³ÉÆ÷Óëг̽øÐÐÐÂÀÏ»®¶Ï£¬Ï¸½ÚȴδµÃµ½ÆÁ±Î?ÒÔĿǰµÄ³ÉÊì¶ÈÀ´¿´£¬µ±Äãдг̴úÂëʱ£¬±ØÐëÏÈÈ¥Àí½âг̡¢Éú³ÉÆ÷µÄÇø±ð£¬future
¶ÔÏóÓë task ¶ÔÏóµÄÖ°ÄÜ£¬loop µÄ×÷Óá£×ÜÖ®£¬Ä¿Ç°ÔÚÉú²ú»·¾³ÖÐʹÓà asyncio ¼¼ÊõÕ»À´½â¾öÎÊÌâ²¢²»Îȶ¨£¬Õâ¸öÉú̬»¹ÐèÒª³Ö¾ÃµÄ·¢Õ¹²ÅÄܳÉÊì¡£
×÷Ϊ³ÌÐòÔ±£¬ÔÚÒ»ÃÅÓïÑÔÉÏÉîÈëͬÑù¿ÉÒÔ´øÀ´ÖªÊ¶µÄ¹ã¶È¡£²»Í¬ÓïÑÔÓв»Í¬µÄÐÔ¸ñ£¬ºÏÊʵŤ¾ß½â¾öºÏÊʵÄÎÊÌ⣬¶øÒÔÒ»Ãû
Python ³ÌÐòÔ±µÄÊÓ½ÇÀ´¿´£¬´ó¿É²»±Ø¼á³Ö¼ÄÏ£ÍûÓÚ asyncio ½â¾ö Python µÄÐÔÄÜÎÊÌ⣬°ÑÔÚ×ÝÏòÉϸ㶮
asyncio ºÍÕâÒ»Ì×гÌϸ½ÚËùÐèµÄʱ¼äÄÃÀ´ºáÏòѧϰ Golang£¬Ñ°Çó¸üºÏÊʸü¼òµ¥µÄ½â¾ö·½°¸£¬´úÂëÒ²¿ÉÒÔÉÏÏßÁË¡£
|