ValueError 兼容性和多行字符串美学?

Pro*_*Gov 3 python error-handling

我正在尝试以简洁、简洁的方式编写 ValueError 消息:

    raise ValueError("Model Architecture Not Recognized. Please ensure that your model's filename contains either"
    """ "vgg" and "16" for a 16 layer VGG model, "vgg" and "19" for a 19 layer VGG model, or "nin" for a Network"""
    " In Network model. Note that filenames are not case sensitive.")   
Run Code Online (Sandbox Code Playgroud)

这对 Python 2.7 和 Python 3 都有效吗?有没有更好的方法来显示多行错误消息?+在用于错误消息的字符串之间不使用 a 是否有任何问题?

aba*_*ert 10

这对 Python 2.7 和 Python 3 都有效吗?

是的,字符串文字串联在Python 2Python 3 中的工作方式相同。

有没有更好的方法来显示多行错误消息?

是的。特别是因为这实际上并不是一个多行错误消息。见下文。

在用于错误消息的字符串之间不使用 + 有什么问题吗?

从语义上讲,没有。相邻的字符串文字被连接成一个字符串值。通过+定义一堆单独的字符串值分隔的字符串文字,然后让 Python 在运行时连接它们。但是,因为编译器知道该表达式仅由不可变常量组成,所以它会将它们合并为一个值。1、2

但实际上,像这样阅读代码可能很困难(尤其是当您尝试在 80 列显示器上阅读它时,例如典型的终端模式编辑器或 Stack Overflow)。作为一名读者,我怎么知道您是打算将三个字符串文字连接成一个值,还是希望将三个字符串文字之间用逗号作为三个单独的值传递给ValueError构造函数?好吧,如果我仔细观察并考虑一下,将另外两个字符串作为额外参数传递给 a 并没有多大意义ValueError(即使它是合法的),而且这些空格使这些字符串看起来像是要放在一起,并且等等......但如果我能不仔细看,向右滚动窗口并思考它就可以理解你的代码会更好。因此,有时值得使用+, 甚至是像反斜杠延续这样丑陋的东西,以避免这种混乱。


如上所述,您还没有生成多行字符串。字符串连接成一条巨线。似乎您已经知道这一点,否则您就不会在第二个和第三个文字的开头添加一个空格。

如果你真的想要一个多行字符串,你可以通过\n在适当的地方添加字符来实现。

但是只写一个多行字符串要容易得多:

raise ValueError("""Model Architecture Not Recognized. Please ensure that your model's filename contains either
    "vgg" and "16" for a 16 layer VGG model, "vgg" and "19" for a 19 layer VGG model, or "nin" for a Network
    In Network model. Note that filenames are not case sensitive.""")
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,使用textwrap,这样您就可以编写在源代码中看起来不错但在输出中看起来也不错的内容:

raise ValueError(textwrap.fill(textwrap.dedent("""
    Model Architecture Not Recognized. Please ensure that your model's
    filename contains either "vgg" and "16" for a 16 layer VGG model, 
    "vgg" and "19" for a 19 layer VGG model, or "nin" for a Network
    In Network model. Note that filenames are not case sensitive.
"""))
Run Code Online (Sandbox Code Playgroud)

但是,如果您希望将其作为回溯的一部分打印出来,而不是说except Exception as e: print(e),它仍然看起来很时髦:

ValueError:  Model Architecture Not Recognized. Please ensure that your model's
filename contains either "vgg" and "16" for a 16 layer VGG model,
"vgg" and "19" for a 19 layer VGG model, or "nin" for a Network In
Network model. Note that filenames are not case sensitive.
Run Code Online (Sandbox Code Playgroud)

更好的解决方案可能是编写一个简短的错误字符串加上一个单独的长(多行,如果需要)描述字符串。您甚至可以ValueError通过转储长字符串来创建自己的子类来表示自己。你甚至可以把这些textwrap东西扔到子类中。那么,你会写,说:

raise ModelArchitectureError(
    "Model Architecture Not Recognized.",
    """Please ensure that your model's
        filename contains either "vgg" and "16" for a 16 layer VGG model, 
        "vgg" and "19" for a 19 layer VGG model, or "nin" for a Network
        In Network model. Note that filenames are not case sensitive.
    """))
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,为ModelArchitectureError的构造函数设置这些默认值,这样你就可以这样做:

raise ModelArchitectureError()
Run Code Online (Sandbox Code Playgroud)

1. 当然,Python不需要这个常量求值,它只是允许它。CPython 2.7 和 3.7、PyPy 6 2.7 和 3.5 以及 Jython 2.7 都可以,但其他一些实现可能不行。在这种情况下,该+版本将具有相同的最终用户可见效果,但需要更多时间和临时内存(可能还有缓存空间和字符串内部表空间)来执行此操作。

2. 如果您编写一个导入钩子,在将代码传递给编译器之前在源代码、令牌或 AST 级别转换代码,则可以想象这两者是不同的,因为它们在编译器/优化器到达之前不会变得相同它。