【问题标题】:Python: Exception handling in generators codePython:生成器代码中的异常处理
【发布时间】:2018-02-27 04:15:21
【问题描述】:

我有以下代码读取用户上传的文件并将其显示在预览页面上,预期的输入文件是纯文本但一些用户抱怨他们收到以下错误,

data = fileObj.read(4194304) 文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py”, 第 698 行,已读 返回 self.reader.read(size) 文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py”, 第 501 行,已读 newchars, decodedbytes = self.decode(data, self.errors) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa9 in position 15: 无效的起始字节

读取文件的 Python 代码:

def gen():
    with codecs.open(file_path, 'r', encoding='utf-8') as fileObj:
        while True:
            # 4MB chunk (4 * 1024 * 1024 Bytes)
            data = fileObj.read(4194304)
            if not data:
                break
            yield data

return Response(gen(), mimetype='text/plain')

如何为生成器编写错误处理程序,它将编码切换为latin-1 并尝试再次读取文件而不是抛出异常?

更新容易失败的示例文件数据:

/*
    Copyright � 2017, J. Wayne Schneider - All Rights Reserved
    Unauthorized copying of this file, via any medium is strictly prohibited
    Proprietary and confidential
    Written by J. Wayne Schneider <jwaynes@gmail.com>, May 2017
*/

【问题讨论】:

    标签: python


    【解决方案1】:

    这将是我的看法。

    def main():
    
        def gen(method):
            with open('path', encoding=method) as fileObj:
                while True:
                    data = fileObj.read(4194304)
                    if not data:
                        break
                    yield data
    
        try:
            rr = [*gen('utf-8')]
        except UnicodeDecodeError:
            rr = [*(gen('latin-1')]
        return Response(rr, mimetype='text/plain')
    

    def main():
    
        def gen():
            try:
                with open('path', encoding='utf-8') as fileObj:
                    while True:
                        data = fileObj.read(4194304)
                        if not data:
                            break
                        yield data
            except (UnicodeDecodeError, UnicodeEncodeError, UnicodeError):
                with open('path', encoding='latin-1') as fileObj:
                    while True:
                        data = fileObj.read(4194304)
                        if not data:
                            break
                        yield data
    
        return Response(gen('utf-8'), mimetype='text/plain')
    

    这是带有try的版本;除了内置到 gen 中,不太可能抛出任何错误。

    【讨论】:

    • 它不起作用,作为响应,Python 发送异常详细信息。
    • 有什么例外?
    • data = fileObj.read(4194304) 文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py”,第 698 行,读取返回 self。 reader.read(size) 文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/codecs.py”,第 501 行,读取 newchars,decodedbytes = self.decode(data, self.errors ) UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa9 in position 15: invalid start byte
    • 你试过答案中的第二个版本吗?
    • 你不认为它会破坏 DRY 规则吗?我有这个想法,但正在寻找更好的解决方案:)
    【解决方案2】:

    一个使用try的例子,除了处理错误:

    def gen():
        with codecs.open(file_path, 'r', encoding='utf-8') as fileObj:
            while True:
                # 4MB chunk (4 * 1024 * 1024 Bytes)
                try:
                    data = fileObj.read(4194304)
                    if not data:
                        break
                    yield data
                except UnicodeDecodeError:
                    #do whatever you want on fail here
                except:
                    raise ValueError('object could not be read, even after we caught the unicode error and did something else.')
    
        return Response(gen(), mimetype='text/plain')
    

    【讨论】:

    • 我不想省略数据,而是想将编码切换为latin-1并尝试再次读取文件。
    • 这是错误的,我在回复 Işık Kaplan
    • if not data: breaktry 语句中的作用是什么?它会完全脱离gen 吗? (为什么不添加另一个except 分支?)
    猜你喜欢
    • 1970-01-01
    • 2012-07-07
    • 2013-11-20
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    相关资源
    最近更新 更多