我有一个针对我的函数的给定输入文件的规则列表。如果在给定的文件中违反了其中任何一个,我希望我的程序返回错误消息并退出。
为了尝试这样做,我编写了以下代码:
编辑史蒂夫莎的代码答案
with open(infile, 'r') as fp:
line = fp.readline().strip()
if not line.startswith('#'):
print ('First line does not start with #')
sys.exit(1)
n = 1
for line in fp.readlines():
d = '(\d+,\d+)'
n += 1
cols = line.strip().split()
i = search(d, line)
if len(cols) != 10:
print('Lenth not equal to 10')
sys.exit(1)
if cols[2] != '+' or '-':
print('Column 2 is not a + or - symbol')
sys.exit(1)
if i and cols[8] != i.group(1):
print('Column 8 is not a comma-separated list of integers')
sys.exit(1)
if i and cols[9] != i.group(1) and len(cols[9]) != len(cols[8]):
print('Column 9 in not a comma-separated list of integers with the exact same number of integers in column 8')
sys.exit(1)
然而,当我运行它时,并非所有的条件似乎都有效。我正在尝试正确地做到这一点?
答案 0 :(得分:3)
这一行错了:
if cols[2] != '+' or '-':
这是正确的:
if not (cols[2] == '+' or cols[2] =='-'):
我建议这样做:
if cols[2] not in ('+', '-'):
另外,我建议你不要致电fp.readlines()
。文件对象fp
用作迭代器,当您迭代它时,您一次得到一行。所以你的循环将成为:
for line in fp:
此外,看起来n
正在跟踪行号?在这种情况下,您可以使用惯用的Python方式,如下所示:
for n, line in enumerate(fp, 1):
enumerate()
接受迭代器并从迭代器返回下一个值以及递增计数。默认情况下,计数从0开始,但您可以选择指定起始编号,就像我在此处所做的那样,从1开始。
最好在Python中使用with
语句打开文件,所以我建议你这样做:
with open(infile, 'r') as fp:
line = fp.readline().strip()
if not line.startswith('#'):
print ('First line does not start with #')
sys.exit(1)
for line in fp:
# process lines here
您展示的代码对我来说并不完全合理。这一行:
i = search(d, line)
您必须已完成from re import search
命令。我实际上建议只做import re
,然后明确调用re.search()
,但我想这是一个偏好问题。无论如何,这会将i
设置为来自re.search()
的匹配组结果(如果匹配失败,则设置为None
)。但是在代码中稍后您正在测试r
而不是i
,并且您从未在我们在此处看到的任何代码中设置r
,所以我不确定它会做什么。我个人使用m
作为匹配组的变量名。
你的正则表达式只匹配一对正整数。没有什么可以计算出有多少整数。 len(cols[8])
正在检查cols[8]
中的字符数。
您正在调用字符串方法函数.split('')
,这是不正确的。在我的系统上,它会引发异常:ValueError: empty separator
只需调用.split()
即可在空格上分割;我假设逗号分隔的整数列表不能有任何空格。
最后,请考虑PEP 8中的指南。您的变量FirstLine
大写为类名而不是变量名;这并没有让我感到困惑,但这有点让人分心。大多数Python社区都遵循PEP 8。
http://www.python.org/dev/peps/pep-0008/
考虑到以上所有因素,我只需重新编写代码:
import sys
def parse_list_of_int(s):
try:
return [int(x) for x in s.split(',')]
except Exception:
return None
with open("test.txt", 'r') as f:
# read line 1
line = f.readline().strip()
if not line.startswith('#'):
print ('First line does not start with #')
sys.exit(1)
# need to start enumerate() at 2 because we pulled line 1 out above
for i, line in enumerate(f, 2):
cols = line.strip().split()
if len(cols) != 10:
print('line {0}: Length not equal to 10'.format(i))
sys.exit(1)
if cols[2] not in ('+', '-'):
print('line {0}: Column 2 is not a + or - symbol'.format(i))
sys.exit(1)
lst8 = parse_list_of_int(cols[8])
if lst8 is None:
print('line {0}: Column 8 is not a comma-separated list of integers').format(i)
sys.exit(1)
lst9 = parse_list_of_int(cols[9])
if lst9 is None:
print('line {0}: Column 9 is not a comma-separated list of integers'.format(i))
sys.exit(1)
if len(lst8) != len(lst9):
print('line {0}: Column 8 and column 9 do not have same number of integers'.format(i))
sys.exit(1)
print('No problems!')
sys.exit(0)
我编写了一个简单的函数来解析整数列表,构建一个Python列表并返回它。然后代码可以实际检查两个列表是否长度相同。