Py 有什么缺点?!

在 2011年12月21日 下午2:24,Zoom.Quiet 写道: > 在昨天内部分享交流中,俺回顾了 PyCon2011China 中透露出的 Py 最新使用/发展和体验; > 最后有同学问: >    Python 有什么缺点!? > > 直接HOLD 住了俺的思路… >    - 是也乎!? >    - 世界上没有完美的语言 >    - Python 相比各种开发语言也有缺点,当然的! >    可是,是什么呢?! > > – 没有 {} ? > – 不支持多CPU ? > > 大家在学习使用过程中,对 Python 有什么失望的地方?! > – 兼听则明 > – 现在不满意的,就是我们努力的方向.. > > PS: > – 俺现场憋出的回答是: >    - 由于 Py 历史上积累的好用模块太多,会导致开发人员更加懒惰,不思进取,不论什么都可以直接搜出可用的现成模块来! > > — > 人生苦短, Pythonic! 冗余不做,日子甭过!备份不做,十恶不赦! > 俺: http://about.me/zoom.quiet > 文字协议: http://creativecommons.org/licenses/by-sa/2.5/cn/ > > — > 来自: python-cn`CPyUG`华蟒用户组(中文Python技术邮件列表) > 规则: http://code.google.com/p/cpyug/wiki/PythonCn > 发言: python-cn@googlegroups.com > 退订: python-cn+unsubscribe@googlegroups.com (向此发空信即退!) > 详情: http://code.google.com/p/cpyug/wiki/PythonCn > 严正: 理解列表! 智慧提问! http://wiki.woodpecker.org.cn/moin/AskForHelp > 强烈: 建议使用技巧: 如何有效地报告Bug http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html

好大的题目,我干脆写完发blog得了。

python的整个系统,我其实有非常多的不满。但是用任何一门语言都是取舍问题,如果有一门语言,库够多,已读,易用,性能高,我毫不犹豫立刻转过去。python的强处在于庞大的库,还有非常好的易读和易用性。但是相比来说,性能一直是个问题。python的实现性能大约和C相差五倍上下。如果是大规模计算问题,大约能差10倍以上。当然,我们可以写C扩展,但是这就不是使用python了。我们也可以说,很多时候我们不需要这么快的速度。这是个事实,但是不改变python性能差的事实。 python不但性能差,还有GIL这个玩意。以至于我现在对高并发计算都采取多进程的模式。多进程模式的通讯效率肯定比多线程低,而且麻烦。

另外,python在底层设计上,也表现出很强的实用主义倾向。这是比较外交术语的词汇,更加直白的说法应当是,混乱,不知所谓。在闭包设计上采用free variable设计,而不是lisp中的environs设计。区别?你试试看在外层闭包中from lib import *。由于引入不定个数名称,free variable无法处理。类似的问题还有LEGB规则,新手往往要花很长时间研究这个例子究竟是怎么错的: a = 1 def f(): print a a = 2 我勒个去,这种反直观反人类的事情都有,还敢说自己易读。

还有坑爹的元编程,这东西根本是坑爹中的坑爹货。如果你用过多重继承,大概就知道python的整个OO系统看起来根本是大型的仿真,到处都是乱糟糟的。C++怎么解决多重继承的?你最好别用(真心说,这可比python更加坑爹)。java怎么解决多重继承的,只能继承Interface。其实这是变相的变成了Interface-Implement模式。python怎么解决的?MRO!为什麽一个类加个__metaclass__就会改变性质啊,为什麽一个类去生成另一个类的写法是——我基本不记得了,反正web.py里面有用到,需要的话去炒栗子吧。为什麽方法要隐藏居然要改名字加__啊。你到底是在做OO还是在看起来像OO的东西上狂打补丁啊魂淡。

lambda表达式弱智。我和人讨论过,lambda是否是图灵完备的。结论还是完备的,不过需要借助Y combinator。何必呢?由于强调lambda的快速特性,因此将lambda强制在一行以内(没有结束标记),导致python其实是没有匿名函数的。一个callback数组写的难过死。

语法糖太多了点,当然,这是纯粹的个人感觉。语法糖是把双刃剑,用的好,可以简化编写和阅读,但是太多,往往容易引入语法混乱和额外的约束。

另外,语言的自构建特性混乱。虽说不是每门语言都强调自构建特性,但是通常而言,都是使用C实现一个内核,由内核实现一些基础操作。再由基础操作实现更复杂的操作。每层的边界都是比较清晰的。谁来告诉我,python中有多少库在移植时是由纯python实现的?库的相互依赖层级是?

python的沙盒化也是个问题,如果沙盒做的够好,我完全可以把python作为一个客户级别的平台。用C写一个很简单的类似浏览器的东西,下载一个URL的python包回去运行(或者仅仅检查更新)。从而保证本地效果/跨平台/安全性。现在?一个都保证不了。我连把一个python包转移到另一台同构设备上都很麻烦(如果两者不是严格匹配,例如系统差异,系统版本差异)无论是web开发还是移动终端开发都必须走传统模式。

30 thoughts on “Py 有什么缺点?!

  1. typo:

    1. 多进程模式的通讯效率肯定比多进程低
    2. 其实这是变相的变成了Interface-Impalement模式

    shell 回复:

    丢人阿。。。。。。
    已经修正

  2. 唉,都在提GIL的问题,其实。。挺好的嘛。
    2.6之前都在鄙视多线程,之后出现了multiprocessing多好啊。

    shell 回复:

    1.线程级别交换数据只需要锁,进程级别需要FIFO/socket/共享内存。你觉得哪个易用?
    2.虽然说这么设计不大常见,如果每个上下文互相之间需要高速的数据通讯呢?
    3.如果有大量客户端会连接上来,服务例程需要访问文件/数据库,或者再访问一些见鬼的第三方程序——这些程序是私有接口,只提供了C库。咋办?协程对C库是无能为力的,每进程模式?

  3. 更多给力吐糟收集在:
    http://wiki.woodpecker.org.cn/moin/MiscItems/2011-12-21

    Shellexy 回复:

    设置系统缺省编码为 utf8 用这个就可以了
    import sys
    reload(sys)
    sys.setdefaultencoding(‘utf8′)

    要沙盒跟浏览器的话,一个变态/省事点的方法是使用 javascript 版 python,
    比如 mozilla 利用 llvm 搞的 Emscripten 就可以弄出 js 的 pyvm,
    http://repl.it/ 这个浏览器跑 python 的 demo

    shell 回复:

    setdefaultencoding比较杯具的是,某些库是硬编码的。
    用js版的python的主要问题是,兼容性太差。没那么多库,还用python干吗?

  4. 1.你找个比共享内存速度更快的方案?
    2.脚本语言里面,除了那一堆FP的,你找个多线程支持的更好的试试?perl?php?ruby?lua?javascript?

    shell 回复:

    @lv, 我没发现正文中哪里提到了共享内存,只有评论中我提到了一句。不过那句的上下文是说,进程级共享内存一定麻烦,比线程麻烦的多。不知道为什么要找速度更快的方案。
    另外,我文中讨论的python语言的问题,可不局限于脚本语言。实际上,本文的题目就是全面吐槽python的劣势——每方面都和最顶尖的解决方案比。如果你觉得这没有道理,同样,用python和C比速度更没有道理吧?如果仅仅要解决我吐槽的每个问题,只要你换成解决的最好的那个语言就好。但是综合起来使用最方便,我还是坚持python。

  5. 感觉lz基本没怎么用过python,看了点tutorial就来抒发情感了。
    这些评论根本就不在关键点上。python本来就是草根语言,python的特性是糙快猛。什么语言特征的完美之类的,想要这些东西的请去用haskell。

    另外,速度的比较lz错的太离谱了。python在语言速度上比c慢2个数量级。
    如果是cpu intensive应用,谁都得用embbed c/c extension方案。如果是io intensive应用,2个数量级的速度差别根本就看不区别来。倒是对内存的使用效率更重要。

    shell 回复:

    @lv, 大哥,我的职业就是python程序员。我每天写python程序,起码超过三年了。相反,我觉得你才是没深入用过python,所以没什么怨念。如果你天天持续使用python,你难道不会吐槽他的字符编码方案么?虽然说起来原理我都了解,可是架不住这个库不行那个库有问题,我要一个个打补丁,烦不烦啊。同样,在写大架构的时候,猛然要用到多重继承多重派生,元编程,元编程再继承,函数里面套函数,装饰器传递不定参数的时候,顿时就会觉得头大如斗。是的,我知道正解是重构。可是我们的python代码大约有10W-100W行,毕竟一个那么大的项目都已经存在了,你让我如何说服老板重构呢?因为这不是正确的使用python的方案?因此让我们花个一年重构吧?
    另外,我为什么吐槽python的速度?如果我的整个应用都是cpu密集的,我可以用java优化到C同等量级的地步,我可以用lua优化到C同等量级的地步,我可以用go假装去写C,可是我无法用Python优化到这个地步。诚然,我可以做C扩展,但是C扩展代码太多了,这就不是python项目了。如果是IO密集操作,python也是非常让人难受的。因为python中只有主线程可以接受信号,而主线程是可能被阻塞的,因此python中多线程下不能对信号做假定。而且真的对io要求高的程序,必须手工实现一些特殊的内存结构和算法——例如追及队列,In Place变换。但是python内置不支持这样的东西,必须去做C扩展。他的list是C++中vector一样的东西,而链表队列是collection.deque——这货是每64个对象进行一次分配的,效率绝对不行,必须用C自己写。关于这点,沈崴的公司就做了类似的事情,用C实现了很多web处理必须的扩展,大概能加速一倍不到。但是这又回到了C级别。另外还有一点不算恶心的恶心——真的需要准确处理的io,必须使用系统级别函数,而不是c级别包装。即python内的os.系列函数。这种东西写着写着,你就会觉得这个根本是一个C的包装,而非python。而C的包装,已经有一个非常好的go在前面呆着了,我何必非用python呢?
    我们公司最近有一个io intensive的应用,实现一个log数据库,要求是高响应速度的添加,允许数据丢失。不允许数据增加型修改,只允许InPlace修改。可能有多节点同步,主节点down后锁定无法改写。节点resume后必须保证所有的InPlace修改无错的同步过来。偶尔突发一次大规模的查询,可能是多表多主键子查询——总之,一切皆有可能。要求将系统的io优化到理论最高值,查询语句需要支持预先编译成执行过程后手工优化——也就是需要支持宏。如果你觉得python很好实现,不妨可以试试看。

  6. 我不明白每方面一定要跟最顶尖的解决方案对比的意义。
    因为各方面的最好的解决方案本身就是互斥的。

    shell 回复:

    @lv, 不错,是互斥的,有时还可以数学证明。但是不能吐槽每个使用中不舒服点,就不能静心思考——这个问题真的无药可救了么?这个问题真的不能优化了么?然后你会发现,其实有不少地方还是可以改的。你说多重继承,真的没有进化的余地了么?lambda,为什么越来越弱了?free variable为什么不能改为environs模式?GIL,真的不能去掉么?python,真的不能再快一点点么?
    如果你没有什么不满,就不可能驱动这门语言演化。同样,你自己也失去了进一步的可能性。

  7. 我用python时间是你的2倍。我精通python和pypy的绝大部分细节。我对python也有我的不满,不过跟你的重合度很少。

    我有我的改造python问题的步骤。可以放个很久以前的东西给你看看:
    http://bbs.nju.edu.cn/bbscon?board=Python&file=M.1236526763.A&num=570

    shell 回复:

    @lv, 如果你用了很久的python,而且精通细节,我想知道你有没有给python官方提供过补丁。我曾经做过一些非官方的补丁,有一个是用于解决free_list的内存不释放问题的。由于我觉得自己实现的并不好,因此没有提交。现在官方已经解决了这个问题。
    这个问题在2.5以前非常的让我困扰,当我做大规模并发链接的处理时,不可避免的要同时产生很多数字对象。然而这个造成的内存开销却无法回收,这点曾经让我困扰很久。最后我决定还是写个补丁来解决这个问题。当然,随着官方解决这个问题,我自己的补丁也没必要了。。。

  8. 你的不满是没有意义的,你没有去思考这些问题背后的原因。比如GIL早就被去除过,但最终被证实性能反而不如现在。PyPy的作者也有用transaction memory的方式去去除GIL的规划。在我看来,你只是在抱怨而已。

    shell 回复:

    @lv, 我知道GIL被除去过,也知道性能无法接受,导致没有变成主流。但是这始终*是一个问题*,而非*根本不是问题*。
    至于解决,我打算使用fp了。毕竟我的目地是解决问题,而不是干掉GIL。
    你的偏好,是在python上不断修正,来解决问题。而我的偏好,正是你所描述的这点——各方面都优秀本身就是不可能的。如果python在并发上如同fp语言一样优秀,那他就是个fp语言——当然,这并非不可能。因此,我在解决高速并发计算问题的时候,压根不会考虑python。当然,如果在这个前提之前,再加上一个尽快解决,那么也许我会考虑使用进程池模式。然而如同我吐槽的那样,进程池要高速数据访问只有做内存共享,但是内存共享本身就使得语言解决方案更加的罗嗦和繁琐。
    又例如,在多重继承问题上,我的解决方案?也许你觉得很吐血——我回归了C的哲学,消除了多重继承,只是用函数和函数归属来进行编程。这种模式我觉得很舒服,彻底消除了继承的问题。可是毕竟不是一种快乐的,没有成本的解决方案。但是我比较了彻底解决python问题的代价,我决定,这个代价和改变编程方法来说还是太大了。
    多编码问题?这个没办法。只能拜托测试部门多用功,我们发现一个问题,打一个补丁。如果实在无法接受,只能用unicode的输入输出来覆盖测试整个库,保证它不会出现异常。如果再无法接受,就只有用其他语言了。
    沙盒问题上,我正在研究几种沙盒方案,不过很坑爹的,目前都没有什么太让人惊喜的结论。如果真的有,我想用于浏览器的改进。
    我不知道你如何得出我在抱怨的。是因为我只说了python的问题,没有说如何解决?我不觉得我的解决方案适用于所有人,这和个人的价值取向有关,也和具体的问题有关。

  9. 我没有提交过补丁,自己的补丁当然做过不少。我完整读过cpython,psyco,pypy的源代码,并对他们做过patch。

    我有个项目甚至是基于custom的python的。那个项目是试图在python中引入erlang的并发特性,运行在AIX环境中。另一个项目是试图让python code运行在cell的SPU之中。上面那个截图不知道你仔细看了没有。这个截图中实现了在运行的状态下动态修改python code(而且修改的内容是即将执行的下一行,而不是替换函数)。这个实现最初也是在cpython下做的。以上各种尝试,在CPython下最后都不能算很成功,这也促使我最终倒向了pypy。

    我认为,cpython已经走进死胡同了,继续跟进已经没太大意义。pypy才是python的未来。

    shell 回复:

    @lv, cpython走进死胡同我还不完全认同,毕竟python还有不少特性可以发展。不过想在cpython上做修改已经非常不容易了,python3就是一个明证。但是pypy是一个未来的方向,这个肯定没错。我最近正在跟debian的mentors讨论,关于是否将pypy加回到debian repos中的。目前最大的烦恼就是这东西的编译步骤太过复杂,需要两步。从使用上说,没什么大问题,但是debian需要定制以使得整个结果符合debian特性(这个称为debian化),这就使得必须有一个人来管理整个过程。不知道你有没有兴趣协调这个事情。
    你的那个东西,在lisp中叫做宏。不过宏的实现更加容易理解,也更加舒服。

  10. GIL的解决要看pypy的TM方案。个人觉得这个方案比较有戏。另外GIL并不是“根本不是问题”,而是个很难解决的问题。我之所以要举例perl/php/ruby/javascript/lua等类似的问题,就是说明这个问题是普遍存在的问题。
    sandbox你可以去看看pypy-sandbox。这个是完美的sandbox。当然你可以说第三方库支持不足。不过pypy的进步是可以期待的。

    我觉得不能理解的地方是,你似乎一直在又想马儿跑又要马儿不吃草。你当然可以直接拿每个领域最完美的解决方案来对比吐槽python的问题,但在我看来这样的吐槽没有意义。

    shell 回复:

    @lv, 是的,正是因为GIL是一个问题,所以我才会提出,在python中,应当使用多进程+协程来解决问题。这不是因为这个方案完美,而是因为绕过了GIL。但是,TM方案更加的消耗内存,JIT也相当的消耗内存。我似乎听谁说过,使用pypy自己编译自己的时候,内存消耗高达8G。如果真是这样,这个就和lisp一样,只能叫做“属于未来的语言”——意思是现在的硬件还不足以支撑。我希望pypy的解决方案能够更加的优秀一些,这样我在权衡的时候就不会过于为难。
    pypy的sandbox倒是完美了,不过如同你所说的,第三方库不足,内存消耗严重。使用pypy作为基础来改进浏览器,我不如直接使用lua。lua根本不存在沙盒的问题,没有经过引入连fs都不能使用,是相当好的跨平台界面编程语言。
    我为什么拿每个领域最强的解决方案来吐槽python的问题?那是因为我一直在说明我的观点——在解决某个特定问题的时候,你知道python不足,为什么不用最强的呢?sandbox不爽?可以用js/lua。写代码的时候太像C,性能又不足?那为什么不用go呢?我这篇文章的目地有两个,一个是说明,什么时候你不应当使用python。另一个则是让大家考虑一下,这些时候是否python真的无药可救。

    shell 回复:

    @shell, 另外,个人觉得ZQ大妈提出这个问题的根本原因,是试图找出——什么时候不应当使用python,python还有什么地方可以发展。你可以看最上面的引文,虽然有些乱。“世界上没有完美的语言,Python 相比各种开发语言也有缺点,当然的!大家在学习使用过程中,对 Python 有什么失望的地方?兼听则明,现在不满意的,就是我们努力的方向..”
    而我的两个目地,正是与此对应。

  11. 眼下我没有更多的精力。再过半年也许可以。我也是深度debian用户。
    cpython也许能在未来继续修正一些边边角角的小问题,或者加点的语法糖什么的。但基于cpython的修改越来越困难,导致他事实上已经失去活力了。
    虽然在目前项目中我还是继续使用cpython,但我已经越来越多的引入rpython,并在可能的情况下优先使用pypy了。

    pypy对第三方包支持目前处于alpha阶段,能用,但很不稳定或者性能很差。另外pypy的编译过程最大的问题是无法并行化和分阶段化。这一点也是pypy的软肋。

    shell 回复:

    @lv, 这个有点像民主精神和实施民主的问题,又有点像鸡和蛋的问题。如果没有大量的用户和关注,也许pypy只能一辈子躺在实验室里。在大量的实际使用中,pypy也许有机会除去性能,不稳定之类的问题——至少可以得到更多库的原作者关注和改善。
    至于pypy自身,你注意到没有。这个是典型的自构建语言,个人觉得非常优美。
    不过我自己也没那个功夫去解决这个问题,也是至少半年不行。

  12. 一般来说,pypy消耗的内存比cpython多30%,并不是很恐怖。编译PyPy的确需要消耗非常多的内存,但不是8G。CPython编译PyPy也需要消耗非常可观的内存。至于消耗内存非常大的极端情况,那是因为在64bit下simple python object本身就要比32bit多耗一倍的内存。

    对我来说,一般来说,选择pypy就意味着多30%的内存消耗和快1倍的速度。在内存是如此白菜的前提下,这个问题根本就不是问题。

    当然对于服务器应用来说因为通常会遇到CPU富裕内存不足的情况,所以这是个问题,但这个问题主要是取舍。

    另外,pypy的作者对于压缩python object的内存占用问题上也做过许多工作,这个问题并没有你说的这么严重。

    shell 回复:

    @lv, 如果只是多了30%,我觉得还是很好接受的。在服务器上,我为了加速应用,常常会大规模使用mc。如果可以以应用服务器增加30%内存的代价把应用加速一倍,我觉得完全可以减少几台mc服务器——毕竟那个对应用类型有严格要求。
    目前我也小规模应用了pypy,没有大规模使用的最主要原因是等待各种库的支持。。。

  13. 个人不推荐去深入了解pypy。在你投入大部分精力的情况下,至少可以消耗半年的时间。

    PyPy现在已经不完全是个实验室产品了。而且PyPy的关注度在逐年上升。PyPy的作者在开始的6年内一直在打基础,几乎是默默无闻的。这种精神是难能可贵的。

    shell 回复:

    @lv, 目前而言,学习pypy不如学习lisp合算。因为pypy始终是一个新产品,而lisp已经存在了很久。更大程度上,那是数学,而不是程序,因此很难过时。
    当然,作为劣势,它很多地方比python夸张多了…

  14. 且不说lisp的劣势问题,lisp有啥好学的?丫就一AST。
    学lisp还不如去学学计算理论,研究研究y calc, pi calc什么的。

    shell 回复:

    @lv, 不加上这些东西,光lisp有什么意思。
    另外,y calc是说Y combinator么?

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>