Trip: 协程 Requests 实战,获取免费代理

2017-12-14 16:42:13 +08:00
 NxnXgpuPSfsIT

本文使用开源协程网络库 Trip,解决验证代理时耗时的问题。

简介

验证大量的网上代理一直是爬虫很麻烦的一个工作。 例如我要发出十万份请求,十个请求一个代理,每个代理验证的延时五秒钟。 那么需要的时间为:

100000 / 10 * 5 = 50000

这就是半天时间了,当然,我们可以开很多的线程。 这里我们开二十个线程运行这样的验证,那么需要的时间为:

100000 / 10 * 5 / 20 = 2500

2500 秒即四十分钟多,不包括抓取和处理,仍旧要消耗大量的时间。

而换用了协程框架后,你可以同时验证大量代理。 即使在一次验证中仅验证一百个代理,需要的时间也会变为:

100000 / 10 * 5 / 100 = 500

十万请求需要的代理在九分钟内就可以完成验证,这还仅是一个线程。 如果开多个线程同时处理还可以达到更快的速度。

另外,等待代理返回请求的过程当中完全不影响处理别的内容。 例如,这一个线程在验证的八分钟内完全可以继续充当公众号服务器继续回复消息,完全不会影响。

开始之前

本文基于依赖库 Trip,请保证更新至最新版本:

python -m pip install trip -U

另外,本文涉及协程,建议使用之前基本了解协程是什么,可以写出一个合格的协程程序。

Trip 兼容 Python 2、3,所以建议使用同样兼容的 Tornado 进行入门了解。

具体实现

由于 Trip 想要在协程的基础上充分还原 Requests 的操作,所以就有一个很简单的转换方式。

先用 Requests 的写法写好,之后将所有的网络连接操作加上yield,就基本没有问题了。

所以,下面的代码应该都不难理解。

获取代理

现在进入正文,首先是一个仅方便测试的代码段。

由于大家都有自己的获取代理的方式,网上免费的代理也多如牛毛,我这里随便就挑了一个做测试:

import re

import trip

def get_proxies(number=10):
    r = yield trip.get('http://www.89ip.cn/apijk/' +
        '?&tqsl=%s&sxa=&sxb=&tta=&ports=&ktip=&cf=1' % number)
    p = re.findall('((?:\d{1,3}.){3}\d{1,3}:\d+)', r.text)
    print(p)

trip.run(get_proxies)

这段代码没什么要说的,89ip是我一分钟前搜来的网站,之后使用正则从中提取代理地址。

验证代理

代理的验证用一个很简单的思路:

所以,这个思路下代码是这样的:

from functools import partial
import trip

def test_proxy(proxy):
    try:
        r = yield trip.get('http://httpbin.org/get', timeout=5,
            proxies={ 'http': proxy, 'https': proxy })
        if 'httpbin.org' not in r.text:
            raise Exception('Invalid reply')
    except Exception as e:
        print('[%s]: FAIL %s' % (proxy, e))
    else:
        print('[%s]: SUCC %s' % (proxy, r.elapsed))
        raise trip.Return(proxy)

trip.run(partial(test_proxy, '58.251.249.152:8118'))

我们这里用了五秒的延时,五秒内没有反应的代理就舍弃。 当然你可以根据自己的需求改为十秒、十五秒。

运行后你就会发现该代理完成了验证,显示了是否验证成功。

你可能会问,这个代码的确跑了五秒钟,和普通的代码有什么区别呢?

区别在于,有了协程,一个线程在这五秒钟里可以跑成百上千个这段代码,详见下面一节。

充分利用这五秒钟

如果你使用过 Tornado 或者一些其他的协程框架一定很熟悉这个操作:

r = yield [future1, future2, future3]

没错,这样三个操作就同时跑了起来 (我知道这不严谨,但看出这不严谨的也不需要我给你夸耀协程的好处了吧)。

所以最简单的,我们的主程序可以这样写:(这段代码不能单独跑,注意)

def main():
    proxies = yield get_proxies(100)
    r = yield [test_proxy(p) for p in proxies]
    print(filter(lambda x: x, r))

第一句话获取 ip,第二句话让他们同时检测,第三句话过滤结果。

完整的代码

所以完整的代码是这样的(这段可以跑了,请随意):

import re, time

import requests, trip

@trip.coroutine
def get_proxies(number=10):
    r = yield trip.get('http://www.89ip.cn/apijk/' +
        '?&tqsl=%s&sxa=&sxb=&tta=&ports=&ktip=&cf=1' % number)
    p = re.findall('((?:\d{1,3}.){3}\d{1,3}:\d+)', r.text)
    raise trip.Return(p)

@trip.coroutine
def test_proxy(proxy):
    try:
        r = yield trip.get('http://httpbin.org/get', timeout=5,
            proxies={ 'http': proxy, 'https': proxy })
        if 'httpbin.org' not in r.text:
            raise Exception('Invalid reply')
    except Exception as e:
        pass
    else:
        raise trip.Return(proxy)

def main():
    proxies = yield get_proxies(100)
    r = yield [test_proxy(p) for p in proxies]
    print(filter(lambda x: x, r))

start_time = time.time()
trip.run(main)
print(time.time() - start_time)

你可以运行一下,还是五秒钟,一百个代理的检测完成了。

之后的话

这里用了最简单的一种主程序的方法,你当然也可以使用更高级些的:

@trip.coroutine
def worker(wl, pl):
    while wl:
        p = wl.pop()
        r = yield test_proxy(p)
        if r:
            pl.append(r)

def main():
    waiting_list, proxies_list = yield get_proxies(100), []
    yield [worker(waiting_list, proxies_list) for i in range(10)]
    print(proxies_list)

这就看你喜欢了。

你如果使用的是 Windows 系统,你可能会发现没法同时进行很多的请求。 这是很正常的问题,Windows 系统使用的是 select,没法同时处理很多请求。

另外,剩下来的抓取应该就不需要我多说了。 Requests 怎么抓,这里也怎么抓,Session、timeout 什么的也全都支持。

最后,有什么我没讲清楚的、想法、建议都可以与我邮件联系或者在文末回复。

望本文能够有所帮助!

6508 次点击
所在节点    Python
29 条回复
GreatMartial
2017-12-14 16:48:16 +08:00
大佬,好久不见。😄
NxnXgpuPSfsIT
2017-12-14 17:02:47 +08:00
@GreatMartial 没有没有,离大佬还差的远
2225377fjs
2017-12-14 17:07:32 +08:00
实在看不懂这个意义何在,代码用法写起来也不是很干净。
gevent 的 patch 之后,requests 直接拿来用就好了。。API 更简洁,性能也很好。
NxnXgpuPSfsIT
2017-12-14 17:46:30 +08:00
@2225377fjs
这就是最基本的协程代码,不干净的点在哪里?
和 Requests 完全相同的操作,而协程代码就是有 yield 和 yield from 的。
gevent 加 patch 永远也不知道会出什么问题,怎么和别的协程框架配合,你可以网上搜一下相关内容的吐槽。
owenliang
2017-12-14 17:48:04 +08:00
python 协程的确烧脑,之前看了看 asyncio 的 API,惨不忍睹。
2225377fjs
2017-12-14 17:57:44 +08:00
@NxnXgpuPSfsIT 呵呵了,各种关键字修饰,这种看起来比写起来还蛋疼的东西有何用,gevent 本身就是一个协程框架,为啥还要与别的协程框架配合? patch 之后可以兼容绝大多数 python 的库,什么 Python 环境下别的协程框架能实现?
有人吐槽说明有人用啊。
有问题不应该首先要解决问题么,难道你认为这半吊子框架能比的上 Gevent ?


“而协程代码就是有 yield 和 yield from 的”。。。呵呵,呵呵,这是你定义的么。?
NxnXgpuPSfsIT
2017-12-14 18:19:47 +08:00
@2225377fjs
首先是这样的,我能理解你对于 gevent 的喜爱,我也认可这是一个很好的框架。我无意冒犯也无意和你争吵,只是和你交流一下可能的优劣。以及毕竟自己的库也写了一些时间,和你阐述一下我觉得他还是有一点用的地方。
关于我说协程代码就是有 yield 和 yield from,我们可以看一下 pep380 和 pep492,我理解这可能很丑,但这就是除 gevent 之外的绝大部分协程,也是 python 官方给出的协程方案。
毕竟 python 的协程是基于生成器产生程序顺序切换的,免不了加关键字。
你觉得装饰器特别丑我也理解,Trip 如果使用 python3 就可以不写任何装饰器,python2 没有 async 关键字,为了给 python2 提供兼容我只能这样,目前我也没有改进的办法,找到我肯定第一时间换个好看的写法。你有什么想法的话可以给我一些指导。
gevent 的话,我说的和别的协程框架配合是这个意思:python 最大的优势之一就是库多,我做什么就有什么库。目前已经有很多协程的库,大部分都是基于基本的增加关键词的协程框架,之后必然会更多。如果 gevent 没法和这些框架很好的兼容,可以想象之后会比其他协程框架少大量的可用库。丧失 python 一个巨大的优势。
关于和 gevent 比,我比不上呀。我只是一个空下来把一些想法试着写出来的普通程序员,能有用最好。是不敢把自己放在大佬的位置上的,水平在那里,我自己知道。
wcsjtu
2017-12-14 18:32:21 +08:00
py2 yield 和 return 不能共用就是蛋疼啊~ 用 raise 返回各种违和感
NxnXgpuPSfsIT
2017-12-14 20:35:51 +08:00
@wcsjtu 是的,py3 用这个库就可以 async 和 return 了
所以我自己在用不是在写教程的时候也都是 3 的写法
2225377fjs
2017-12-14 20:45:00 +08:00
@NxnXgpuPSfsIT 既然你回答了这么多,那我也得回一下才行啦,

gevent 最大的一个优势就是可以与很多现有库兼容,api 也非常干净,性能也是 python 环境下最好的了,到你这里却变成了一个劣势,明明 gevent 自己就是一个协程库却还要去兼容别的协程库,这是什么逻辑?

另外 async 就不丑了?看看 go 的设计,与 gevent 的思路非常相似,这才是好用的方案,有优雅的实现不用,要用蹩脚的实现,也是醉了。

大家都是普通程序员,不更应该去学习掌握好用开源库,优点被你说成缺点,你确定你很了解 gevent,都还没有了解掌握就说这个东西的缺点是啥,然后去造一个自己心目中好用的轮子,这种思路不对吧?
难道普通就要去造轮子?造的轮子还不好用。

既然你说这框架的优点是与别的库配合起来方便,那么我就问一个问题,如何在这个库的协程并发环境下方便的访问 mongodb,访问 mysql,访问 redis,访问 kafka,rabbitmq,zookeeper 等常用的外部系统?既然都是协程了,那么肯定是要同步的 API 方式吧。我看好像不方便吧,那你再去看看 gevent 的环境下这些功能是怎么实现的?

这个问题解决了就更容易回答这两个库谁的实用性更好了吧。

最后,协程并发最大的优势是效率非常高,所以才能在很多环境下碾压线程并发,但是 Python 生成器翔一样的性能,估计也就只剩下了包装同步访问这一个作用了吧。
NxnXgpuPSfsIT
2017-12-15 04:40:20 +08:00
@2225377fjs
你认为 gevent 是优雅的高效的产物,而我想告诉你实际上他只是一个没有办法的将就。

首先,关于讨论,
技术或者项目经验存在高低,是否能意识到 gevent 存在的问题都无所谓,我们可以慢慢交流。
但是你希望还是可以认识到没有进行充分的论证,指责他人的工作毫无意义是一件很没有礼貌的事情。
另外,措辞体现一个人的素质,尊重这件事情也是相互的,于人于己应该都是有利的。


说他是将就,是因为:
* gevent 会给项目带来毁灭性的隐患,且无法预料
* 不区分协程函数和普通函数(不使用 yield )是一个很糟糕的习惯
* 侵入式的兼容只能产生一个不可知的过渡用品,而不是一个有保障的产品

所以需要非基于 gevent 的重新实现:
* 他不会给程序埋下无法发现的隐患
* 他使用了更好的协程习惯
* 他每一个方法都有保障,不会充满了不可知


我的观点里有一个大局,一个细节。


说大局,
主要是希望你把我放在一个同等的位置上听一下我说的话,讨论才能有意义。
把我当成一个一无所知的跳梁小丑的话,可能你也提不起兴致和我交流。
当然,如果你可以拿出你的项目让我认同,我也不介意自己以跳梁小丑的身份虚心求教。

以我浅薄的见识看到的大局里,我不是一个人固执己见倾向于使用 yield 等关键字。
和你讲一下我看到的大局,那些大牛都是怎么看待 gevent 的。

Python 之父明确表明过 gevent 不是一个好的实现
你可以在他的 Twitter 里看到: https://twitter.com/gvanrossum/status/443093650533142528
gevent 早已出现,而加入标准库的是 asyncio 而非 gevent 更是对这一态度的明确实践。

Requests 的作者对于本类项目的期待是我写这个项目的初衷。
Requests 的作者一直认为使用 gevent 不是一个好的做法,他多次在 grequests 的 issue 中提出希望有基于 Future 和 yield 语法的协程 Requests。
例如 Issue#10 和 Issue#51,他提出这是一个好的想法,但是他没有时间实现。
( Issue#10: suggestion: use concurrent.futures instead of gevent 中他这样说道:
I'm 100% for this now — i've been talking about it for a few months now. Just need to implement ;))
在 gevent 和其他的基于 yield 的协程的选择中,他百分百的站在了 gevent 的对立面。

不说国外,国内学习 Python 多多少少听说过董伟明,特别是 Web 开发一块。
他在个人的博客中明确表明:所以建议大家放弃 Gevent,拥抱 asyncio。
http://www.dongwm.com/archives/使用 Python 进行并发编程-我为什么不喜欢 Gevent/)


说细节,
是希望我们可以在讨论中把优劣讨论的越来越清楚。
我就回复开始的三个点一个一个解释:

关于隐患,先上一个特别简单的代码:
import multiprocessing, grequests; manager = multiprocessing.Manager()
他报错了,如果不是这段代码非常简单的只有一个引用,你需要多久要怎么发现是 gevent 的问题?
另外,这个问题你需要怎么修复?
所以就有了很多报出 gevent 毁了他整个项目的情况: https://github.com/kennethreitz/grequests/issues/55,https://github.com/pytest-dev/pytest-xdist/issues/254
不仅如此,关于垃圾回收,gevent 也会导致问题: https://www.projectcalico.org/the-sharp-edges-of-gevent/
更不要说一些操作的误区,例如使用 RLock,却发现明明都是主线程却没法锁两次。

使用 gevent 你难免会陷入是不是 gevent 又出问题了和完全没有修理的头绪的噩梦当中。
所以我说 gevent 是一颗定时炸弹,而我的项目不是,所以我认为我的项目有意义。

关于习惯,
董伟明关于习惯有一段话说得很好,我就不画蛇添足了:
Gvanrossum 说用它就是” patch-and-pray ”,太形象了。
由于 Gevent 直接修改标准库里面大部分的阻塞式系统调用,包括 socket、ssl、threading 和 select 等模块,而变为协作式运行。
但是我们无法保证你在复杂的生产环境中有哪些地方使用这些标准库会由于打了补丁而出现奇怪的问题,那么你只能祈祷( pray )了。
在 Python 之禅中明确说过:「 Explicit is better than implicit.」,猴子补丁明显的背离了这个原则。
我认可这个观点,即使仅是为了服务持有这个观点的这些人,我也认为我的项目有意义。

关于三方库,
你说 gevent 最大的一个优势就是可以与很多现有库兼容,api 也非常干净,我同意。
gevent 通过侵入式的修改让一些三方库直接可用,这很棒。
但这只是不可预知的部分可用,例如 Requests,你了解哪些部分是无法像预期那样表现的吗?
另外,这些部分哪些是可以修复的,哪些是框架所限无法修复的呢?
所以才需要一个让 Requests 所有部分功能都明确可用的库才出现。
你提到了很多外部系统,本项目基于 tornado,你可以将这些和 tornado 或者 asyncio 进行配对搜索,你就能发现全都有相应支持。
反观 gevent,kafka 的支持我并不认可 Github 上那个仅有 11 Star 长久未更新的项目,rabbitmq、zookeeper 之流更是不堪。
我不满足于不可预知的部分可用,所以我认为这个项目有意义。

当然还有一点是效率,
你并没有证明你所提出的相对于其他协程解决方案的高效,这里提一下,希望可以在后面的交流中看到。
另外,在证明的时候还是希望可以考虑到 gevent 对于 Python 解释器的限制。


最后,感谢你的时间,也期待你的回复!
2225377fjs
2017-12-15 09:11:31 +08:00
所以需要非基于 gevent 的重新实现:
* 他不会给程序埋下无法发现的隐患
* 他使用了更好的协程习惯
* 他每一个方法都有保障,不会充满了不可知

这都是你自己说的吧。。。。。

引经据典这么多,看起来你不是读书太多了就是读书太少了,好多我看还是直接 copy 网上的文章吧,这么快餐。

看起来你就是这个库的作者吧,也是呵呵了。。。

“反观 gevent,kafka 的支持我并不认可 Github 上那个仅有 11 Star 长久未更新的项目,rabbitmq、zookeeper 之流更是不堪。 “

你知道用的是哪个库么?自己都不清楚就开始胡说,还更是“不堪”,一会说自己是普通程序员,一会又自以为是的指点江山。

还要跟你证明其他 Python 其他协程方案效率不行,你自己去证明吧。

redis,mongodb,rabbitmq,zookeeper,etcd,requests,mysql 这些系统的相关库我们在生产环境跑的好好的,还有不少服务节点是跑在 pypy 下的,最开始想喷的就是,不要不了解情况就开始说人家这不好,那也不好,然后自己撸一个自以为是的半吊子的框架出来,Node.js 环境下就是这种太多了,各种各样的半吊子框架。

普通程序员,既要谈大局,还要谈细节,你让我很不懂啊。
NxnXgpuPSfsIT
2017-12-15 09:53:32 +08:00
@2225377fjs
换言之,你的回复告诉了我你不能就 gevent 的缺陷做出任何解释,也无法证明你唯一提出的观点高效。

你认为 gevent 是优雅的高效的产物,而我告诉了你实际上他只是一个没有办法的将就。
所以需要非基于 gevent 的重新实现:
* 他不会给程序埋下无法发现的隐患
* 他使用了更好的协程习惯
* 他每一个方法都有保障,不会充满了不可知

我说的,我证明了。

而你空无一物的嚣张回答,相较于想要好好交流的同行,更倾向于一个无脑的喷子。

我不想引战,所以各有优劣的观点我也每一个好好阐述。
Python 之父,Requests 作者,董伟明的观点我摆出来了。
可能产生的问题的代码,issue,原理我也摆出来了。

而不像你,
说都有相应支持,却一个也举不出来,告诉我你指的是什么? kafka、rabbitmq、zookeeper,我洗耳恭听。
说 gevent 性能也是 python 环境下最好的,谁提出谁举证的道理不会不懂吧,没有举证就不要乱说。

你说:“不要不了解情况就开始说人家这不好,那也不好”,送还给你。

你不了解 yield, yield from,我把 pep 找给你看。
你看不到 gevent 也存在自身巨大的缺陷,我找大牛找代码找原理和你讲。

我的所有开源项目都在 github 上,你才知道我是这个库的作者吗?
大家都是普通程序员所以我从来没有因为我写过几个项目就觉得自己很了解什么。
而你随意指责别人的项目是半吊子,不拿出实际的理由也不给出足以信服的个人背景。
不好意思,我不能接受。

所以可以麻烦把你自信的来源向我展示一下吗?
让我看看你到底写过什么。
如果你想继续讨论而非无脑喷,请好好证明一下你的观点。
xin053
2017-12-15 10:12:44 +08:00
上面那位兄弟,请尊重别人,作为一个旁观者,明显可以感受到人家心平气和的跟你讨论,而你满口火药味。

最开始关注这个作者是使用他的微信个人公众号库,后来又去研究他的微信公众号库(顺便吐槽一下,github 上该库几个 PR 都木有处理,虽然看到源码有些不太正确的写法,不过也没提 PR,想着作者应该没时间来维护这个也就算了)

大概在二月前的时候我就开始研究 python 协程这一块,好像是一个月前吧,当时看到 littlecodersh 的仓库上有个新提交的 trip 库,简单看了看,基于 Tornado 和 requests 封装的一个协程库,当时想着,用 python3 的协程库就好了,就没太细看,然后过几天就看到作者在各平台开始宣传这个库了,我对这个库也只是旁观没实际在生产上使用过。但等项目慢慢成熟之后,我肯定是会尝试的。

再就是关于轮子的看法,关于 python 协程的三方库也有好几个,之所以有这么多,肯定是现存的库或多或少有些不足或者不方便,更重要的是,写个轮子肯定能加深对这方面的理解。你都没看人家的源码,甚至说都没使用过,你就认为是"撸一个自以为是的半吊子的框架出来",说什么"Node.js 环境下就是这种太多了,各种各样的半吊子框架",你有能力吐槽别人写的是半吊子框架,有本事自己写一个出来啊,没本事就别 bb,你不用自然有人用好吧。对于那些吐槽别人库烂的人,我只想说,你不尊重别人的劳动成果也就算了,你可以选择不用,也没人强求你用,问题是,你 tm 都没好好研究过,bb 个毛

另外对于 Gevent,我想你是真的没有遇到过项目出 bug 是因为 Gevent 替换了底层库造成的,你是不懂这种事情有多坑。
2225377fjs
2017-12-15 11:56:25 +08:00
@xin053
@NxnXgpuPSfsIT

不好意思,我们公司内部服务框架不开源,你们还是自娱自乐自己的撸自己的野路子轮子吧。

如果我说我们之前做服务框架的时候,几人完全阅读掌握了 greenlet 源码及其原理,libev,完全掌握了 gevent 的协程调度模型以及各种实现原理,而且我们内部对 gevent 的协程调度做了很多 hook,这样你觉得我有资格评价 gevent 不?

正是有这个底气才敢出来说,你以为随便乱说的?
贴几篇当年学习 greenlet 与 gevent 时候做的记录:

http://blog.csdn.net/fjslovejhl/article/details/38824963
http://blog.csdn.net/fjslovejhl/article/details/45956339
http://blog.csdn.net/fjslovejhl/article/details/39153861

知道自己水平不行,所以用好现有的轮子就好了,有问题自己就去解决,我有自知之明,不敢随便撸轮子。

“另外对于 Gevent,我想你是真的没有遇到过项目出 bug 是因为 Gevent 替换了底层库造成的,你是不懂这种事情有多坑。”
别自己 yy,好不
2225377fjs
2017-12-15 12:51:34 +08:00
@NxnXgpuPSfsIT
@xin053

我说他是 翔一样的性能,你不信,随便测一下,下面两段代码自己看看输出吧:

import trip
num = 0
import time
before = time.time()
test_time = 200
all_length = 0

def main():
global num
global all_length

r = yield trip.get('http://www.ccb.com/')
num += 1
all_length += len(r.content)
if num == test_time:
after = time.time()
print after - before
print "all length :" , all_length

for _ in xrange(test_time):
trip.run(main)

out:
12.0239999294
all length : 55200


-------------------------------------------
num = 0
import time
before = time.time()
test_time = 200
all_length = 0



import gevent.monkey
gevent.monkey.patch_all()
import gevent

import requests
threads = []


def _task():
global all_length
r = requests.request("GET", "http://www.ccb.com/")
all_length += len(r.content)

for _ in xrange(test_time):
threads.append(gevent.spawn(_task))

for t in threads:
t.join()

print time.time() - before
print "all length :", all_length

out:
0.721999883652
all length : 55200
--------------------------------------------------------------

所以我说是翔一样的性能没有冤枉它吧,或者说只是你这个库的性能是这样的而已。
2225377fjs
2017-12-15 12:59:43 +08:00
@NxnXgpuPSfsIT 或者说我的测试有误,不知道你的库的并发是怎么弄,也不知道你的库怎么弄 join 这种类似的原语,你可以按照你自己的逻辑去测试上面类似的业务,
并发同步访问 www.ccb.com N 次就行,看看耗时。(暂时没空去研究你的库怎么做这些功能)
NxnXgpuPSfsIT
2017-12-15 14:44:26 +08:00
@2225377fjs
gevent 的侵入导致的 bug 我已经举出了那么多例子,不再多做解释。再次提醒,他会给程序埋下无法发现的隐患。

很遗憾,我发现你竟然是在完全不了解框架的情况下与我进行的交流。
所谓的性能差距竟然是来源于你完全不了解 Python 官方主流协程的运行方式,也没有花哪怕三分钟了解一下这个项目或是 tornado 或是 asyncio 的入门。
你打字的时间远不止三分钟,相较你说的没空,嚣张怕是更适合你。

关于回答,你依旧无法做出任何实质性的回答。
很意外,你无法 show me the code,哪怕是一个空余时间的小项目,而论证的唯一一个观点竟是这样的水平。
然而不出所料的,你依然出言不逊,展示着你的自负。
抱歉,这样的话,我没有时间和你浪费。

言尽于此,嚣张和自负背后往往有相适应的能力与才华,我真心希望你有但我没能发现。
不再回复,祝好!
2225377fjs
2017-12-15 16:20:52 +08:00
@NxnXgpuPSfsIT 哈哈,按你说的我喷你的框架没啥鸟用是嚣张,那你有没有想过自己根本没有深入使用 gevent 就开始说 gevnet 这不行那不行,是不是你也不咋样啊,举出来的例子还全是网上随便搜出来的例子,你能举出你在实际使用功能中遇到了什么天坑的例子么?

这种随便网上搜一下,然后复制粘贴一下来证明自己的观点,还是那句,是不是有点太快餐了?

我是没法 show code,因为我知道自己几斤几两,不会轻易去撸轮子,也不喜欢到处贴自己的代码,但是我起码贴出了我自己的记录的博客文章,你可以去看看我够不够格评价 gevent,是不是对 gevent 足够了解呢?

我确实没有时间去了解你那我看来可能没什么用的库,因为我用 gevent 可以很简单的实现你的各种 sample。

即便 gevent 有各种问题,好歹人家好用啊,你的 sample 的例子我没看出来哪一个 gevent 实现不了啊。。而且 gevent 实现起来更简单更干净啊。你说我为啥还要花时间去了解你的库呢?

yes,我最开始就承认自己是普通程序员,所以哪个好用我就用哪个,被 node.js 现在各种半吊子库的环境弄的很恼火,所以很鄙视这种动不动自己就上手撸轮子的行为。

gevent 是有一些天坑,我们在实际使用中也遇到了坑,但是没有不能解决的问题,你敢保证你的库就没有 bug 了? 按你对的协程的理解和定义,是不是 go 的协程环境也是很不标准呢?毕竟 gevent 的原理机制和 go 非常类似.

我最开始的问题就是 gevent 能很好的实现你的库展示的各种功能,而且人家能提供的功能更丰富,为啥还要去撸一个轮子,因为这样才能体现自己牛逼?你说 gevent 有问题,那么你请告诉 gevent 实现你演示的各种功能,会遇到什么 bug ?更或者说会遇到什么不能解决的 bug ?

在实际生产环境下到底哪个库更堪用一些,你既然要上网公开环境的推广你自己的库,那么你起码你要有一定的理由告诉我这一开始就对你的库表示质疑的人吧,这种 gevent 有 a,b,c 等等问题,网上一搜,一罗列的回答,显然这没有啥说服力吧,这就是我一开始的问题。

而且对你这样回答:“ gevent 加 patch 永远也不知道会出什么问题,怎么和别的协程框架配合,你可以网上搜一下相关内容的吐槽”, 你应该说“你永远不知道会出什么问题”,还上网搜个毛啊,你都不知道出什么问题,搜出来的都是跟你一样的,有何用。
guyskk0x0
2017-12-15 17:02:30 +08:00
@2225377fjs #19 我认为你根本不懂协程,也完全不了解框架

你说 "trip 翔一样的性能",是因为你不懂协程,你的测试程序根本没有并发。

楼主帖子里有这样一段,你看出哪里不严谨了吗?

```
r = yield [future1, future2, future3]
没错,这样三个操作就同时跑了起来 (我知道这不严谨,但看出这不严谨的也不需要我给你夸耀协程的好处了吧)。
```

楼主也举了 gevent 的例子,你说你懂 gevent,麻烦解释一下?

```
关于隐患,先上一个特别简单的代码:
import multiprocessing, grequests; manager = multiprocessing.Manager()
他报错了,如果不是这段代码非常简单的只有一个引用,你需要多久要怎么发现是 gevent 的问题?
另外,这个问题你需要怎么修复?
```

不懂就别装懂,没有理据就别乱喷。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/414753

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX