python3 代码不会在 doctest 中产生错误,但在 运行 不使用 doctest 时工作

python3 code not produces error in doctest but working when run without using doctest

"""
>>> ip_tuple = process("2\t1.001451000\t192.168.0.24\t\t10.0.0.5\t\t98\t84\t\t\t\t\t\t\t\t1")

"""
import doctest
def process(line):
    list_lines = line.split('\t')
    return (list_lines[2], int(list_lines[7]))

doctest.testmod()

当我 运行 它时,我希望它通过所有测试,但会产生以下输出:

e/lab4/Q9# python3 solution.py
**********************************************************************
File "solution.py", line 2, in __main__
Failed example:
    ip_tuple = process("2       1.001451000     192.168.0.24            10.0.0.5                98      84
                                              1")
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.6/doctest.py", line 1330, in __run
        compileflags, 1), test.globs)
      File "<doctest __main__[0]>", line 1, in <module>
        ip_tuple = process("2       1.001451000     192.168.0.24            10.0.0.5                98      84
                                                  1")
      File "solution.py", line 8, in process
        return (list_lines[2], int(list_lines[7]))
    IndexError: list index out of range
**********************************************************************
1 items had failures:
   1 of   1 in __main__
***Test Failed*** 1 failures.

奇怪的是,当我去掉 docstring 和 运行 与测试相同的代码时,生成以下文件:

def process(line):
    list_lines = line.split('\t')
    return (list_lines[2], int(list_lines[7]))

ip_tuple = process("2\t1.001451000\t192.168.0.24\t\t10.0.0.5\t\t98\t84\t\t\t\t\t\t\t\t1")
print(ip_tuple)

没有产生错误,打印了以下输出:

('192.168.0.24', 84)

请解释为什么会这样。

docstring 提供原始字符串,所以所有 \t 都被视为转义的 \t,所以实际上 split('\t') 并没有真正起作用如你所料。

这也可以通过在文档字符串中添加调试打印来确认:

"""
>>> test_string = "2\t1.001451000\t192.168.0.24\t\t10.0.0.5\t\t98\t84\t\t\t\t\t\t\t\t1"
>>> print(test_string.split('\t'))
"""

产出

['2', ' 1.001451000     192.168.0.24', '     10.0.0.5', '', '  98      84', '', '', '', '', '', '', '', '      1']

转义文档字符串中的 \t 有效:

import doctest

def process(line):
    """
    >>> ip_tuple = process("2\t1.001451000\t192.168.0.24\t\t10.0.0.5\t\t98\t84\t\t\t\t\t\t\t\t1")
    """
    list_lines = line.split('\t')
    return (list_lines[2], int(list_lines[7]))


doctest.testmod()

顺利通过。

编辑

将整个文档字符串设为原始字符串也可以解决此问题。

import doctest

def process(line):
#   V note the r for raw string
    r"""
    >>> ip_tuple = process("2\t1.001451000\t192.168.0.24\t\t10.0.0.5\t\t98\t84\t\t\t\t\t\t\t\t1")
    """
    list_lines = line.split('\t')
    return (list_lines[2], int(list_lines[7]))

doctest.testmod()

顺利通过。