Python xlrd: suppress warning messages

前端 未结 5 1766
暖寄归人
暖寄归人 2021-01-02 10:19

I am using xlrd to process Excel files. I am running a script on a folder that contains many files, and I am printing messages related to the files. However, fo

相关标签:
5条回答
  • 2021-01-02 10:36

    Based on John Machin's answer, here is some working code (tested with Python 3.6) that works with sys.stdout:

    import io
    import sys
    import xlrd
    
    path = "somefile.xls" # path to an XLS file to load or a file-like object for one
    encoding_override = None
    
    # Mute xlrd warnings for OLE inconsistencies
    class LogFilter(io.TextIOWrapper):
        def __init__(self, buffer=sys.stdout, *args, **kwargs):
            self.buffer = buffer
            super(LogFilter, self).__init__(buffer, *args, **kwargs)
        def write(self, data):
            if isinstance(data, str):
                if not data.startswith("WARNING *** OLE2 inconsistency: "):
                    super(LogFilter, self).write(data)
            elif isinstance(data, bytes):
                super(LogFilter, self).write(data.decode(self.buffer.encoding))
            else:
                super(LogFilter, self).write(data)
    
    def open_workbook(file_contents, encoding_override):
        logfilter = LogFilter()
        return xlrd.open_workbook(file_contents=file_contents, logfile=logfilter,
                                  encoding_override=encoding_override)
    
    if hasattr(path, 'read'):
        book = open_workbook(file_contents=path.read(), encoding_override=encoding_override)
    else:
        with open(path, 'rb') as f:
            book = open_workbook(file_contents=f.read(), encoding_override=encoding_override)
    
    0 讨论(0)
  • 2021-01-02 10:37

    Check out the relevant part of the xlrd docs. The 2nd arg of the open_workbook function is logfile which should be an open file object or act-alike. All it needs to support is a write method. It defaults to sys.stdout.

    So, something like this (untested) should do the job:

    class MyFilter(object):
        def __init__(self, mylogfile=sys.stdout):
            self.f = mylogfile
        def write(self, data):
            if "WARNING *** OLE2 inconsistency" not in data:
                self.f.write(data)
    
    #start up
    log = open("the_log_file.txt", "w")
    log_filter = MyFilter(log)
    book = xlrd.open_workbook("foo.xls", logfile=log_filter)
    
    # shut down
    log.close()
    # or use a "with" statement
    

    Update in response to answer by @DaniloBargen:

    It's not xlrd that's writing the newline separately, it's the Python print statement/function. This script:

    class FakeFile(object):
        def write(self, data):
            print repr(data)
    
    ff = FakeFile()
    for x in "foo bar baz".split():
        print >> ff, x
    

    produces this output for all Pythons 2.2 to 2.7 both inclusive:

    'foo'
    '\n'
    'bar'
    '\n'
    'baz'
    '\n'
    

    A suitably modernised script (print as a function instead of a statement) produces identical output for 2.6, 2.7, 3.1, 3.2, and 3.3. You can work around this with a more complicated filter class. The following example additionally allows a sequence of phrases to be checked for:

    import sys, glob, xlrd
    
    class MyFilter(object):
        def __init__(self, mylogfile=sys.stdout, skip_list=()):
            self.f = mylogfile
            self.state = 0
            self.skip_list = skip_list
        def write(self, data):
            if self.state == 0:
                found = any(x in data for x in self.skip_list)
                if not found:
                    self.f.write(data)
                    return
                if data[-1] != '\n':
                    self.state = 1
            else:
                if data != '\n':
                    self.f.write(data)
                self.state = 0
    
    logf = open("the_log_file.txt", "w")
    skip_these = (
        "WARNING *** OLE2 inconsistency",
        )
    try:        
        log_filter = MyFilter(logf, skip_these)
        for fname in glob.glob(sys.argv[1]):
            logf.write("=== %s ===\n" % fname)
            book = xlrd.open_workbook(fname, logfile=log_filter)
    finally:
        logf.close()
    
    0 讨论(0)
  • 2021-01-02 10:38

    The answer by John works, but has a small problem:

    xlrd writes that warning message and the following newline character separately to the logfile. Therefore you will get an empty line in your stdout instead of the message, if you use the filter class proposed by John. You shouldn't simply filter out all newlines from the log output either though, because there could be "real" warnings that would then be missing the newlines.

    If you want to simply ignore all log output by xlrd, this is probably the simplest solution:

    book = xlrd.open_workbook("foo.xls", logfile=open(os.devnull, 'w'))
    
    0 讨论(0)
  • 2021-01-02 10:40

    For what it's worth I had the same warning message; when I deleted the first row (which was empty) the warning disappeared.

    0 讨论(0)
  • 2021-01-02 10:48
    import warnings
    
    def fxn():
        warnings.warn("deprecated", DeprecationWarning)
    
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        fxn()
    

    -> http://docs.python.org/library/warnings.html#temporarily-suppressing-warnings

    0 讨论(0)
提交回复
热议问题