从python 迁移到GO

转载 2013年12月04日 14:06:49

这是一篇(长)博文, 介绍了我们在 Repustate 迁移大量 Python/Cython 代码到 Go 语言的经验。如果你想了解整个故事,背景和所有的事情,请继续往下读。如果你只是想了解 Python 开发者在一头扎进 Go 语言前需要了解什么,请点击一下链接:

从Python迁移到Go的建议(Tips & Tricks)

 

背景

在 Repustate,我们完成过的最棒的技术成就之一是实现了阿拉伯语的情感分析。阿拉伯语是一块难啃的硬骨头,因为它的词形变化相当复杂。比起譬如英语,阿拉伯语的分词(将一个句子切分呈几个独立的单词)也更困难,因为阿拉伯语的单词本身还可能会包含空白字符(例如:“阿列夫”在一个单词里的位置)。这也谈不上是泄密,Repustate 使用支持向量机(SVM)来获取一个句子背后最有可能的含义,并在其中加上情感元素。 总体上来说,我们使用了 22 种模型(22 个 SVM) 并且在一篇文档中,每一个单词我们都会加以分析。因此如果你有一篇 500 字的文档,那么基于 SVM,会进行十万次的比较。

 

Python

Repustate 几乎完全就是一个 Python 商店。我们使用 Django 来实现 API 和网站。因此(目前)为了保持代码一致,同时使用 Python 来实现阿拉伯语情感引擎是合情合理的。只是做原型和实现的话,Python 是很好的选择。它的表达能力很强悍,第三方类库等等也很好。如果你就是为了Web服务,Python 很完美。但是当你进行低级别的计算,大量依赖于哈希表(Python 里的字典类型)做比较的时候,一切都变慢了。我们每秒能处理大约两到三个阿拉伯文档,但是这太慢了。比较下来,我们的英语情感引擎每秒能处理大约五百份文档。

 

瓶颈

因此我们开启了 Python 分析器,开始调查是什么地方用了那么长时间。还记得我前面说过我们有 22 个 SVM 并且每个单词都需要经过处理吗?好吧,这些都是线性处理的,非并行处理。所以我们的第一反应是把线性处理改成 map/reduce 那样的操作。简单来说:Python 不太适合用作 map/reduce。当你需要并发的时候,Python 算上好用。在 2013 Python 大会上(译者:PyCon 2013),Guido 谈到了 Tulip,他的这个新项目正在弥补 Python 这方面的不足,不过得过段一段时间才能推出,但是如果已经有了更好用的东西,我们为什么还要等呢?

 

选 Go 语言,还是回家算了?

我在Mozilla的朋友告诉我,Mozilla 内部正在将他们大量的基础日志架构切换到 Go 语言上,部分原因是因为强大的 [goroutines]。Go 语言是 Google 的人设计的,并且在设计之初就把支持并发作为第一要务,而不是像 Python 的各种解决方案那样是事后才加上去的。因此我们开始着手把 Python 换成 Go 语言。

虽然 Go 代码还不算正式上线的产品,但是结果非常令人鼓舞。我们现在能做到每秒处理一千份文档,使用更少的内存,还不用调试你在 Python 里遇到:丑陋的多进程/gevent/“为什么 Control-C 杀不了进程”这些问题。

 

为什么我们喜欢 Go 语言

任何人,对编程语言是如何工作(解释型 vs 编译型, 动态语言 vs 静态语言)有一点理解的话,会说,“切,当然 Go 语言会更快”。是的,我们也可以用 Java 把所有的东西重写一遍,也能看到类似更快的改善,但那不是 Go 语言胜出的原因。你用 Go 写的代码好像就是对的。我搞不清楚到底是怎么回事,但是一旦代码被编译了(编译速度很快),你就会觉得这代码能工作(不只是跑起来不会错,而且甚至逻辑上也是对的)。我知道,这听上去不太靠谱,但是确实如此。这和 Python 在冗余(或非冗余)方面非常类似,它把函数作为第一目标,因此函数编程会很容易想明白。而且当然,go 线程和通道让你的生活更容易,你可以得到静态类型带来的性能大提升,还能更精细的控制内存分配,而你却不必为此在语言表达力上付出太多的代价。

 

希望能早点知道的事情(Tips & Tricks)

除去所有这些赞美之词以后,有时你真的需要在处理 Go 代码的时候,相对于 Python,改变一下思维方式。因此这是我在迁移代码时记录的笔记清单 —— 只是在我把 Python 代码转换到 Go 时从我脑子里随机冒出来的点子:

  • 没有内建的集合类型(必须使用map,并检查是否存在)
  • 因为没有集合,必须自己写交集,并集之类的方法
  • 没有 tuples 类型,必须写你自己的结构,或者使用 slices (即数组)
  • 没有类似 \__getattr__() 的方法,你必须总是检查存在性,而不是设置默认值,例如,在 Python 里,你可以这样写 value = dict.get(“a_key”, “default_value”)
  • 必须总是检查错误(或者显式的忽略错误)
  • 不能有变量/包没被使用,因此简单的测试也需要有时注掉一些代码
  • 在 [] byte 和 string 之间转换。 regexp 使用 [] byte (不可变)。这是对的,但是老把一些变量转换来转换去很烦人
  • Python 更宽松。你可以使用超出范围的索引在字符串里取一个片段,而且不会出错。你还可以用负数取出片段,但是 Go 不行
  • 你不能混合数据结构类型。也许这样也不太干净,但是有时在 Python 里,我会使用值是混合了字符串和列表的字典。但是 Go 不行,你不得不清理干净你的数据结构或者使用自定义的结构
  • 不能解包一个 tuple 或者 list 到几个不同的变量(例如:x, y, z = [1, 2, 3])
  • 驼峰式命名风格(如果你没有首字大写方法名/结构名,他们不会被暴露给其它的包)。我更喜欢 Python 的小写字母加下划线命名风格。
  • 必须显式检查是否有错误 != nil, 不像在 Python 里,许多类型可以像 bool 那样检查 (0, “”, None 都可以被解释成 “非” 集合)
  • 文档在一些模块上太散乱了,例如(crypto/md5),但是 IRC 上的 go-nuts 很好用,提供了巨大的帮助。
  • 从数字到字符串的转换(int64 -> string) 和 []byte -> string (只要使用 string([]byte))不太一样。需要使用 strconv。
  • 阅读 Go 代码比起 Python 那样写起来如伪代码的语言更像一门编程语言, Go 有更多的非字母数字字符,并且使用 || 和 &&, 而不是 “or”和“and”
  • 写一个文件的话,有 File.Write([]byte) 和 File.WriteString(string), 这点和 Python 开发者的 Python 之道:“解决问题就一种方法 ”相违背。
  • 修改字符串很困难,必须经常重排 fmt.Sprintf
  • 没有构造函数,因此惯用法是创建 NewType() 方法来返回你要的结构
  • Else (或者 else if)必须正确格式化,else 得和 if 配对的大括号在同一行。奇怪。
  • 赋值运算符取决于在函数内还是函数外,例如,= 和 :=
  • 如果我只想要“键”或者只想要 “值”,譬如: dict.keys() 或者 dict.values(),或者一个 tuples 的列表,例如:dict.items(),在 Go 语言里没有等价的东西,你只能自己枚举 map 来构造你的列表类型
  • 我有时使用一种习惯用法:构造一个值是函数的字典类型,我想通过给定的键值调用这些函数,你在 Go 里可以做到,但是所有的函数必须接受,返回相同的东西,例如:相同的方法签名
  • 如果你使用 JSON 并且 你的 JSON 是一个复合类型,恭喜你。 你必须构造自定义的结构匹配 JSON 块里的格式,然后把原始 JSON 解析到你自定义结构的实例中去。比起 Python 世界里 object = json.loads(json_blob) 要做更多的工作

 

是不是值得?

值得,一百万倍的值得。速度的提升太多了,以致很难舍弃。同时,我认为, Go 是目前趋势所在,因此在招新员工的时候,我认为把 Go 当作 Repustate 技术积累的重要一环会很有帮助。

Python 开发者在迁移到 Go(lang) 时需要知道哪些事?

本文最早由 Repustate 发布,主要介绍将代码迁移至 Go(lang) 时的注意事项。文章系国内 ITOM 管理平台 OneAPM 编译呈现,以下为正文。...

我为什么放弃了 Python ,选择了 Go?

随着人工智能、物联网、数据科学等领域的兴起,Python 迅速升温,成为诸多开发者的首选入门语言。然而就在一片追随声中,不少开发者从 Python 转向了 Go 语言,这究竟是什么原因?在本文中,来自...
  • csdnnews
  • csdnnews
  • 2017年10月20日 11:38
  • 13283

c++、c#、Python、GO语言基本语法比较

c++、C#、Python、GO语言基本语法比较

Go和Python Web服务器性能对比

Go和Python Web服务器性能对比 2011-08-05 13:41 renwofei423 开源中国社区 我要评论(0) 字号:T | T 我通常使用Python来...

为什么我不会舍弃Python投奔Go语言

最近,由于一篇“为什么我不会舍弃Python投奔Go语言(英文)”的博客,我收到了大量的邮件,这篇文章中,作者说Go语言除了“用返回值来处理异常错误”这点外,其它的都非常好。我想写出一点东西,解释一下...
  • cometwo
  • cometwo
  • 2013年03月02日 18:58
  • 857

C语言、python、go、C#版本选择排序

多语言同步学习也是个不错的享受

放弃Python转向Go语言:我们找到了以下9大理由

转用一门新语言通常是一项大决策,尤其是当你的团队成员中只有一个使用过它时。今年 Stream 团队的主要编程语言从 Python 转向了 Go。本文解释了其背后的九大原因以及如何做好这一转换。 ...

5种方式将机器学习带到Java、Python以及Go等编程语言

5种方式将机器学习带到Java、Python以及Go等编程语言 机器学习目前炙手可热,本文搜集了Java、Python以及go等编程语言中常见且实用的开源机器学习工具,对机器学习感兴趣的开发者或...

从Python切换到Go的九大理由

原文:Why we switched from Python to Go 作者:Thierry Schellenbach 翻译:雁惊寒 摘要:本文介绍了Stream网站从Python切换到Go的...
  • js_gary
  • js_gary
  • 2017年11月02日 09:13
  • 112

用http实现文件共享(python和go语言示例)

http://www.cnblogs.com/MikeZhang/archive/2012/02/11/httpFileSharePythonAndGo.html 平时工作中少不了文...
  • bellwhl
  • bellwhl
  • 2013年06月26日 17:31
  • 975
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:从python 迁移到GO
举报原因:
原因补充:

(最多只允许输入30个字)