2013年七月月 发布的文章

Python脚本命令行变量的实现

我们知道Make工具是支持命令行变量的,这种手段为我们提供了很好的灵活性,我们可以通过敲入不同的命令行参数来决定Makefile脚本的行为。

make [variable1=value1 variable2=value2 ... ... ]。

#
# Makefile
#

CMODE = 64-bit

ifeq ($(CMODE), 64-bit)
    CFLAGS += -m64
endif
  
all:
    gcc $(CFLAGS) -o foo foo.c

$> make
gcc -m64 -o foo foo.c

$> make CMODE=32-bit
gcc -o foo foo.c

近期我们的一个Python脚本工具也有类似的需求了,但Python脚本原生并不支持这种命令行变量,我们来看看是否可以利用Python提供的机制实现一种可以满足我们需求的命令行变量。

我们的期望结果如下:

$> foo.py fruit=apple

# foo.py

flag = '' #这个定义可以有,也可以没有,如果有,可以理解为默认值

….

if flag == 'apple':
    ….
elif flag == 'orange':
    ….
elif flag == 'banana':
    ….
else:
    ….

Python是动态语言,提供了注入eval、exec等在运行时执行代码的能力。我们要实现命令行变量的机制,离不开这些能力的支持。eval用于求值表达式,而x=y是语句,我们只能用exec。

【#1】

import sys

if __name__ == '__main__':
    c = len(sys.argv)
    if c <= 1:
        print "found zero command variable"
        exit(0)

    exec(sys.argv[1])

    if fruit == 'apple':
        print 'this is apple'
    elif fruit == 'oracle':
        print 'this is orange'
    elif fruit == 'banana':
        print 'this is banana'
    else:
        print 'other fruit'

$> foo.py fruit=apple

Traceback (most recent call last):
  File "./foo.py", line 18, in <module>
    exec(sys.argv[1])
  File "<string>", line 1, in <module>
NameError: name 'apple' is not defined

上面的例子执行后,提示'apple'没有定义。执行foo.py fruit="apple"得到的也是同样的错误。从内部输出来看,无论是fruit=apple还是fruit="apple",exec的参数始终都 是fruit=apple,导致exec抱怨apple这个符号没有定义。

我们打开一个Python命令行交互窗口,做如下测试:

$> python
Python 2.7.3 (default, Aug  1 2012, 05:14:39)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> exec("fruit=apple")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'apple' is not defined
>>> exec("fruit='apple'")
>>> fruit
'apple'
>>> exec("num=1")
>>> num
1

通过这个小实验可以看出,我们不能将命令行参数直接原封不动的传给exec,我们要对其进行一下加工,加工的效果如下:

fruit=apple => fruit='apple'
num=1 => num=1

【2】

import sys

def __convert(source):
    (var, sep, val) = source.partition("=")
    if val.isdigit():
        return source
    return  var + "=" + "\'" + val + "\'"

if __name__ == '__main__':
    c = len(sys.argv)
    if c <= 1:
        print "found zero command variable"
        exit(0)

    exec( __convert(sys.argv[1]))

    if fruit == 'apple':
        print 'this is apple'
    elif fruit == 'orange':
        print 'this is orange'
    elif fruit == 'banana':
        print 'this is banana'
    else:
        print 'other fruit'

__convert函数对命令行的参数做了转换,对于数值类的var直接原封不动的返回,否则对于值为字符串的var,将其val用''包裹起来后返回。我们来测试一下新程序:

$> foo.py fruit=apple
this is apple
$> foo.py fruit=orange
this is orange
$> foo.py fruit=watermelon
other fruit

从输出结果来看,我们的预期是达到了^_^。上面的程序只是示例性质的,Python的exec具有运行时执行动态代码的能力,我们在获得这种强大能力的 同时,也面临着巨大的风险。一旦恶意代码从外部传入被exec执行,将带来严重的后果。因此对于exec要执行的代码务必要预先进行必要的形式校验。

代码评审,由人治过渡到“法治”

事实证明:有效的代码评审(Code Review,也有叫代码审查的),对保证代码质量具有十分重要的作用。因此这两年来我一直尝试着在这块不断改进和完善,以期望能形成一套合理、规范、有 效且高效的代码评审流程,这包括引入在线代码评审系统、走查和在线评审结合、规范评审Request的规模与有效性、设立评审专员等,用心不可谓不良苦 ^_^。大家也的确形成了及时提交Code Review Request或组织进行代码走查的良好习惯。不过我还是发现了一些问题。

* 有些组(我对其影响力不足的^_^)依旧没有严格执行代码评审环节,代码屡屡出现低级错误;
* 走查形式的会议评审缺乏全面性,效果好坏与参与者的“状态”直接相关;
* 在线评审环节缺乏“责任制”,常出现的一种情况是:请求大家评审,结果可能却是大家都没有评审。出现"Request Review Miss"的现象。

这让我陷入思考:长期以来我们在代码评审这块过于依赖人的自觉性,理想地认为每个人都能认识到代码评审的重要性,并认真地执行代码评审的流程或充满激情地 参与到其他人发起的代码评审过程中去,但结果事与愿违。这就像党员如何保持纯洁性一样,如果仅仅依靠个人道德/职业水平约束,这事往往是不成的。事实证明 人治在中国社会是会造成各种社会问题的。我们的代码评审环节也是一样,我们不能再期望所有人都能和我站在一条认知和激情水平线上,于是我打算尝试向“法 治”过渡。

"法",规则制度也,是团队一致认同的可以提升产品质量的规则制度。以此为前提,我要做的就是设立“检查和预防”机构,即以很低的Cost,检查大家是否按“法”完成了代码评审环节,提醒大家要按“法”进行。我采取了几个措施:

【规范Commit Log

这是一个前提工作。实现规范的Commit Log便于后续的检查和监督,同时细化规范的Commit Log信息对代码维护是大有裨益的。在Commit Log中还增加了一些关联信息,方便维护者了解该Commit的背景。初期的模板是这么来确定的:

模板结构:

TITLE
BODY
RELATIONSHIPS

展开后如下:

[Category] Title content

Body content

[BUGID] QC#733 | JIRA#766
[REVIEWID] RB#767
[REVIEWED BY] xx, yy, zz
[SIGNOFF BY] xx

TITLE Category:
   – BUGFIX 代码修复
   – FEATURE 新功能特性添加
   – TASK 诸如代码美化、调整版本号等
   – URGENT 紧急提交,对此类commit,可不做review和拦截

BODY Content:
   有关此次修改的详细信息说明

RELATIONSHIPS:
   – [BUGID] 一般用Bug跟踪系统的ID号
   – [REVIEWID] reviewboard上的ID号
   – [REVIEWED BY] xx, yy, zz
   – [SIGNOFF BY] xx

【"全覆盖"原则

所有变更代码都要发起在线“Code Review Request”,即便是会议走查的代码,会后也要补提“Review Request”。

【“低保”原则

每个Review Request至少选择两名评审负责人,填到"Request"中,这两个人必须对此Request给出评审意见,这是一个评审的最低保障了,这总比没有人评审要好。当然了其他人也都可以参与评审。只有这两名评审负责人明确提交"ship it" Comment后,该代码才算是通过评审。

【关键路径拦截】

"对不起,若不符合规定,你的工作将无法进行下去"。有了统一的Commit Log模板,我们就可以对大家的代码Commit环节做检查和拦截了。如果代码没有进行评审,无法填写模板中的字段内容,那代码将无法提交到代码库中。如 果虚构Commit log内容,这将是极大的错误,在抽查中一旦发现,后果将是很严重的^_^。

当然这一过程中还有很多细节需要考虑,比如Reviewer的选择不能集中在一个人身上,否则会造成热点;再比如紧急提交代码应该如何处理等等。“法治” 是与一定的“国情”相匹配的,并不是所有的组织都需要进行这么严格且略有死板“法治”手段,依团队内组员的专业能力和认知水平而定。

有些公司开发了自己的统一开发平台,将一系列流程都在一套系统中规范了起来,这当然是更好的“法治”了。但在没有这样的平台的前提下,初步使用上述的几个手段,还是会收获一些改进的。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats