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

Python ValueError兼容性和多行字符串美学?,python,error-handling,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 Ne

我正试图以简洁明了的方式编写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.")   
这对Python2.7和Python3都有效吗?有没有更好的方法来显示多行错误消息?在用于错误消息的字符串之间不使用
+
是否存在任何问题

这对Python2.7和Python3都有效吗

是的,字符串文字连接在和中的工作方式相同

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

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

在用于错误消息的字符串之间不使用+是否存在任何问题

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

但实际上,像这样的代码很难读取(特别是当您试图在80列显示器上读取它时,如典型的终端模式编辑器或堆栈溢出)。作为一名读者,我如何知道您是希望将三个字符串文本连接成一个值,还是希望将三个字符串文本(它们之间带有逗号)作为三个单独的值传递给
ValueError
构造函数?好吧,如果我仔细看看,仔细想想,把另外两个字符串作为额外参数传递给
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.""")
或者,更好的方法是使用,这样您就可以编写源代码中看起来不错但输出也不错的内容:

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.
"""))
但如果您希望将其作为回溯的一部分打印出来,而不是,比如说,
,例外情况为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.
更好的解决方案可能是编写一个简短的错误字符串,再加上一个单独的长(如果需要,可以多行)描述字符串。您甚至可以通过转储长字符串来创建自己的
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.
    """))
或者,更好的是,为
ModelArchitectureError
的构造函数设置这些默认值,这样您就可以执行以下操作:

raise ModelArchitectureError()

一,。当然,Python不需要这个常量计算,它只允许它。CPython 2.7和3.7、PyPy6 2.7和3.5以及Jython 2.7都可以做到这一点,但其他一些实现可能无法做到。在这种情况下,
+
版本将具有相同的最终用户可见效果,但需要更多的时间和临时内存(可能还有缓存空间和字符串intern表空间)


二,。如果您在将代码传递给编译器之前编写一个导入钩子,在源代码、令牌或AST级别对代码进行转换,那么这两个钩子可能会有所不同,因为在编译器/优化器到达之前,它们不会变得相同。

可能的重复不是多行。另外,我希望错误消息简短而精确,这样我可以在文档中查找它们。所以我应该尝试进一步简化消息?我想,包括如何纠正这个问题,比告诉用户去查找它要简单得多。如果你希望它是多行的,为什么不把它写为一个多行字符串,在一对“代码>”“”/>代码中?(你也可能想考虑<代码> TXTWRAP < /代码> ping它,但是……)