Mock Python's built in print function

前端 未结 11 1948
醉话见心
醉话见心 2020-12-06 09:10

I\'ve tried

from mock import Mock
import __builtin__

__builtin__.print = Mock()

But that raises a syntax error. I\'ve also tried patching

11条回答
  •  太阳男子
    2020-12-06 09:30

    If you want to stick with the print statement from 2.x as opposed to the print() function from 2.x, you could mock your sys.stdout instead.

    Write a dummy "file", perhaps in about this way:

    class Writable(object):
        """Class which has the capability to replace stdout."""
        newwrite = None
        def __init__(self, oldstdout, newwrite=None):
            self.oldstdout = oldstdout
            if newwrite is not None:
                self.newwrite = newwrite
        def write(self, data):
            self.newwrite(self.oldstdout, data)
        @classmethod
        def subclass(cls, writefunc):
            newcls = type('', (cls,),
                dict(write=lambda self, data: writefunc(self.oldstdout, data)
            return newcls
    

    This class expects to be combined with a writing function which gets the printed data. This writing function is supposed to take 2 arguments: the first one with the "old stdout" to be used for printing at the end, and a further one for the data.

    Let's take

    def mywrite(sink, data):
        sink.write(data.encode("hex"))
    

    for that.

    Now you can do

    import sys
    sys.stdout = Writable(sys.stdout, mywrite)
    

    or you can do

    @Writable.subclass
    def mywritable(sink, data)
        sink.write(data.encode("hex"))
    
    sys.stdout = mywritable(sys.stdout)
    

    The 2nd version is a bit trickier: it creates a subclass of the Writable with the help of a decorator function which turns the given function into a method of the new class created instead and put into the name where the given function comes from.

    After that, you have a new class which can be instantiated with the "old stdout" as argument and can replace sys.stdout after that.

提交回复
热议问题