Python可变参数与标准输出的重定位

使用Python的内置函数print支持可变参数,也就是说,print的调用参数是不固定的。例如:

  1. # 一个参数  
  2. print "Hello China!"  
  3. # 两个参数  
  4. print "Your name is", name  
  5. # 三个参数  
  6. print "The number of", what, "is", count, "!"  

在Python里使用*和**来设置可变参数,它们的区别是*传递一个参数列表(准确来说是参数元组),**传递一个参数字典。二者可以同时混合使用。

  1. >>> def printArgs(*argList, **argDict):  
  2. ...     print "argList =", argList, ", argDict =", argDict  
  3. ...   
  4. >>> printArgs("The end of the world is"2012, lastMan = "Xiaoxia")  
  5. argList = ('The end of the world is'2012) , argDict = {'lastMan''Xiaoxia'}  

下面举一个例子来模仿print的实现,

  1. >>> import sys  
  2. >>> def myprint(*argv):  
  3. ...     sys.stdout.write(" ".join([str(i) for i in argv]) + "\n")  
  4. ...  
  5. >>> print "I believe"2012"is the end of the world."  
  6. I believe 2012 is the end of the world.  
  7. >>> myprint("I believe"2012"is the end of the world.")  
  8. I believe 2012 is the end of the world.  
  9. >>> print "tuple:", (123), "list:", [123], "dict:", {"begin":-2012"end":2012}  
  10. tuple: (123) list: [123] dict: {'begin': -2012'end'2012}  
  11. >>> myprint("tuple:", (123), "list:", [123], "dict:", {"begin":-2012"end":2012})  
  12. tuple: (123) list: [123] dict: {'begin': -2012'end'2012}  

print默认是输出到stdout中,在终端运行的程序,无重定向的情况下,print输出到控制台。如果要做代码里实现把print的输出写入到log文件中,可以通过修改stdout的文件对象来实现。同理,重定位标准输入和标准错误输出分别修改stdin和stderr的文件对象即可。

下面的例子捕捉所有print的输出,让输出的每一行前增加一个时间的显示:

  1. import sys, time  
  2.   
  3. class MyOutput():  
  4.     def __init__(self, fd):  
  5.         self.formatTime()  
  6.         self.out = fd  
  7.         self.newLine = True  
  8.           
  9.     def formatTime(self):  
  10.         return time.strftime("%H:%M:%S  ", time.localtime())  
  11.           
  12.     def write(self, s):  
  13.         if self.newLine:  
  14.             self.out.write(self.formatTime())  
  15.             self.newLine = False  
  16.         self.out.write(s)  
  17.         if s.endswith("\n"):  
  18.             self.newLine = True  
  19.       
  20.     def flush(self):  
  21.         self.out.flush()  
  22.       
  23. sys.stdout = MyOutput(sys.stdout)  
  24.   
  25. print "Program begin."  
  26. mylist = [54321]  
  27. print "prev:  ", mylist  
  28. mylist.sort()  
  29. print "after: ", mylist  
  30. time.sleep(3)  
  31. print "Program end."  

运行效果:

root@xiaoxia-pc:~/桌面# python redirect.py
02:25:41 Program begin.
02:25:41 prev: [5, 4, 3, 2, 1]
02:25:41 after: [1, 2, 3, 4, 5]
02:25:44 Program end.

Python可变参数与标准输出的重定位》有32个想法

  1. whitefirer

    python里不仅可以重定向到文件或者输出,还可以重定向到内部对象:
    from StringIO import StringIO
    import sys
    buff =StringIO()

    print >> buffer, ‘Hello,’, ‘Xiaoxia’, 44
    print buffer.getvalue()

    这个操作甚至还不用保存标准I/O流

    回复
            1. whitefirer

              即使是像我说的那样buffer 是一种类型,它也应该可以被赋值!!!只不过是不好的行为。所以,我们都有点觉得你的版本是不是高了或低了…

              回复
                1. whitefirer

                  真神奇!你还是没说版本,在2.6下是可以被赋值的,只是这个buffer从此以后就不是类型了,所以最好就换个变量,比如Xiaoxia。要注意它是只读的!用python的sqlalchemy从数据库中读出一段二进制数据读过来的类型就是,这时我们再转成自己要的类型,比如string,当然对就字符串你就不得不应付编码这一琐事…
                  >>> s = ‘Hello world’
                  >>> t = buffer(s, 5, 6)#原型 buffer(object[, offset[, size]]),可以用help(‘buffer’)了解到
                  >>> t

                  有趣的是,Python Tutorial 不止一次把buffer当一般变量用,比如12. 10. 2 Read bytes into a buffer,12. 10. 3 Read entire file into a buffer。这东东还真是很少用到!

                  回复
                  1. whitefirer

                    这次的引号绝对没问题,我是从shell上拷下来的,不知道它为什么会变成这样,还有尖括号它会吞掉!
                    test:
                    ”半角
                    ‘’全角
                    尖括号

                    回复
    1. Xiaoxia 文章作者

      这个很棘手啊!!!目前我只知道可以这样用:

      >>> import ctypes
      >>> c = ctypes.cdll.LoadLibrary(“libc.so.6”)
      >>> ret = c.printf(“%d is the end of the world!”, 2012)
      2012 is the end of the world!

      回复
      1. 元谷

        好像还有一个很古老的模块,好像是dll模块吧!也能读取动态库!!!不过在3。X的版本后不支持它了!!!

        回复

回复 Xiaoxia 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据