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

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

# 一个参数
print "Hello China!"
# 两个参数
print "Your name is", name
# 三个参数
print "The number of", what, "is", count, "!"

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

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

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

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

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

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

import sys, time

class MyOutput():
    def __init__(self, fd):
        self.formatTime()
        self.out = fd
        self.newLine = True
        
    def formatTime(self):
        return time.strftime("%H:%M:%S  ", time.localtime())
        
    def write(self, s):
        if self.newLine:
            self.out.write(self.formatTime())
            self.newLine = False
        self.out.write(s)
        if s.endswith("\n"):
            self.newLine = True
    
    def flush(self):
        self.out.flush()
    
sys.stdout = MyOutput(sys.stdout)

print "Program begin."
mylist = [5, 4, 3, 2, 1]
print "prev:  ", mylist
mylist.sort()
print "after: ", mylist
time.sleep(3)
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的版本后不支持它了!!!

        回复
    1. Xiaoxia 文章作者

      可以啊,没问题!!!我可以帮你搭建的,你的VPS没有用作别的网站用途即可。

      回复

发表评论

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

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