Python sys 模块

来源:互联网 发布:天高云淡秒赞4.0源码 编辑:程序博客网 时间:2024/05/16 23:56

这次的主题是python的sys模块,个人觉得sys模块就是为了开发软件用的,之前有接触到过的就是用argv获取命令行参数。此外,说起sys模块,通常我都会同时用到os模块,今天就稍微进阶一下这两个模块吧。


sys最重要的功能大概是获取参数argv了,格式为sys.argv,先打开一个Hello.py文档,写入


import sysprint sys.argv


然后打开命令行输入

$python Hello.py a b cd e f
['Hello.py', 'a', 'b', 'cd', 'e', 'f']$

从结果可以发现,argv的实现应该非常简单,就是把python之后的所有东西当作一个字符串,然后对该字符串执行string.split(" ")返回一个列表。这个实现虽然非常简单,但几乎已经能用这个接口完成所有命令行程序所需要的参数输入工作了。


再看看sys还有什么有趣的方法
>>> import sys>>> dir(sys)['__displayhook__', '__doc__', '__egginsert', '__excepthook__', '__name__', '__package__', '__plen', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_getframe', '_mercurial', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'hexversion', 'last_traceback', 'last_type', 'last_value', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'py3kwarning', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions']>>>
个人用过的有exit和path,exit不用说,写在程序内部,一旦触发就能结束程序的。path则会显示python的所有搜索路径,以列表形式存储,并且可以在运行时使用append增加搜索路径,比较方便。

接下来是os模块,os模块个人最常用的是os.system()可以直接调用命令行程序,比如Blast,这个特性让我对Python爱不释手,虽然后来知道perl等高级语言也有类似的功能。这个命令让我用Python制作了不少Pipeline以及命令行程序的wrap。

sys和os搭配使用可以写出一些比较有意思的命令行程序,比如linux下ln命令默认是硬链接一个文件(hard link),其实我们电脑上所有的文件都是硬链,链接到硬盘上的某一地址,所谓的普通链接,其实是对硬链的地址的链接,也即传说中指针的指针,因此硬链并没有复制文件,而是复制了硬盘上的地址,所以和“源文件”是等同的一个链接,简单的说硬链的文件删掉源文件(源链)还能打开,而普通链接删掉源文件(源链)就打不开了。言归正传,ln是个好程序,但是这个命令并没有-r的选项,即只能一个一个硬链,如果我希望硬链一个文件目录下所有的文件怎么办?比如我想硬链我的Dropbox文件夹下的所有文件,这样即使在其他电脑上误删并且不小心同步了,也有一个硬链拷贝在本地,既不占地方又能实时更新。出于这个想法,我写了个ln_all的小程序,wrap了ln的命令。

主程序如下:


#!/usr/bin/env python# coding:utf-8# Author: bingwang# Email: toaya.kase@gmail.com# Copylight 2012-2012 Bing Wang# LICENCES: GPL v3.0__docformat__ = "epytext en"import osimport sysignore = ['.DS_Store']def main():    if len(sys.argv) != 3:        print sys.argv        sys.exit("\033[91m ln_all take exactly 2 arguments\033[0m")    path_from = sys.argv[1]    path_to = sys.argv[2]    if not path_from.startswith("/"):        path_from = "%s/%s" % (os.getcwd(),path_from)    if path_from.endswith("/"):        path_from = path_from[:-1]    if not path_to.startswith("/"):        path_to = "%s/%s" % (os.getcwd(),path_to)    if path_to.endswith("/"):        path_to = path_to[:-1]    os.system("mkdir -p %s" % path_to)    for (now_path, dirs, files) in os.walk(path_from):        now_path = now_path.replace(" ","\\ ").replace(",","\\,").replace(";","\\;")        target_path = path_to + now_path[now_path.find(path_from)+len(path_from):]        for d in dirs:            d = d.replace(" ","\\ ").replace(",","\\,").replace(";","\\;")            os.system("mkdir %s/%s" % (target_path,d))        for f in files:            if f not in ignore:                f = f.replace(" ","\\ ").replace(",","\\,").replace(";","\\;")                os.system("ln %s/%s %s/%s" % (now_path,f,target_path,f))if __name__ == "__main__":    main()

此外,这个程序还有一个用处是可以wrap命令行的rm命令,具体我还没实现,目的是rm之后的东西丢到一个回收站的文件目录下,而不是直接删掉,我曾经就干过一个相当二的事情,写了个rm /Application/的命令然后居然没有让输入密码……结果把mac下所有的应用给删掉了……

今天的sys模块就到这里,下次的题目是word count,嗯,貌似也不是很难哦,学了今天的os.system(),明天的实现只需要os.system('wc %s'%filename)就可以了的样子。anyway,下次还是要认真的研究一下其他实现方法。


===============================================================================
附:
这些“习题”源自陈皓叔叔的博文《程序员练级技术攻略》:
http://coolshell.cn/articles/4990.html
我希望尝试跟着他推荐的方式练级,同时把每日的心得放到博客上来供大家分享,也希望各位程序员大牛们指导。

原创粉丝点击