python中的文件验证,更好的方法和原因

时间:2017-06-07 17:29:58

标签: regex python-2.7 validation string-literals

我正在开展一个涉及解析文件以插入本地数据库的工作项目。为了编写高效的健壮代码,我试图看看验证文件的最佳方法是什么。我写了两个python脚本:

EXPECTED = 'PubNo|Name|CoverID|Issue|CustomLabel|Split'

with open('test.txt', 'r') as f:
    lines = f.readlines()

test = lines[0].replace(" ", "").strip()

if test[-1] == '|' or test[0] == '|':
    test = test.strip('|')

if test.lower() == EXPECTED.lower():
    print 'Successful Match!'
else:
    print 'Bad match :('

import re

with open('test.txt', 'r') as f:
    lines = f.readlines()

patt = re.compile(r"\|?PubNo\|Name\|CoverID\|Issue\|CustomLabel\|Split\|?", re.I)

test = re.sub(r"\s", "", lines[0])
m = re.match(patt, test)

if m.group():
    print 'Successful Match!'
else:
    print 'Bad match :('

我希望很明显,我正在使用简单的字符串文字比较和各种格式化来确保一些安全性,以及纯粹依赖于正则表达式的版本。任何人都可以解释这两种方法的优缺点吗?它们都花费相同的时间来执行,并且都具有相当的可读性。到目前为止,我能看到的唯一优势是使用正则表达式意味着在比较字符串文字之前不必进行如此多的手动格式化。

1 个答案:

答案 0 :(得分:2)

假设你没有看到加载整个文件的问题,并假设你修复你的正则表达式(你呈现它的方式程序会在不匹配时中断,你应该检查是否有匹配,而不是如果有是其中的一个群体)这两个不一样。考虑文件的第一行:

statement.executeUpdate("INSERT INTO myDB2"+ " ( columnRows,  columnA, columnB)"
    + " VALUES ( "+rows+", "+a+", "+b+")");`

你的正则表达式'验证器'会标记它成功,你的字符串比较不会。如果您希望第一列“验证器”精确匹配该字符串而不是其他任何内容,则必须将正则表达式模式更改为PubNo | Name | CoverID | Issue | CustomLabel | Split | SomethingMore 。此外,你的正则表达式'验证器'将消耗'替换'部分中的所有空格字符,包括标签,字符串比较器不会。

所有条件都相同 - 在两种情况下,字符串搜索都会相当更快 - 而且不计算正则表达式引擎的加载,准备模式和所需的所有其他支持结构。即使你缓存模式,并删除正则表达式的所有缺点,字符串比较仍然会更快。考虑如下设置:

r"\|?PubNo\|Name\|CoverID\|Issue\|CustomLabel\|Split\|?$"

这将涵盖两种方法(严格且仅匹配开头)的两种情况。您没有考虑构建正则表达式模式以忽略空格,因此您不需要替换,但它不会显着加快速度(实际上,它可能会比这更慢)。

现在,如果您有3个文件,比如import re VALID = "PubNo|Name|CoverID|Issue|CustomLabel|Split" # prepare the regex patterns PATTERN_VALID = re.compile(r"\|?{}\|?".format(VALID.replace("|", r"\|"))) PATTERN_STRICT = re.compile(PATTERN_VALID.pattern + "$", re.I) CLEAR_WHITESPACE = re.compile(r"\s") # let's not disadvantage the string compare, too VALID_LOWER = VALID.lower() def string_valid(data): if data.strip("| ").replace(" ", "").lower().startswith(VALID_LOWER): return True return False def string_valid_strict(data): if data.strip("| \r\n").replace(" ", "").lower() == VALID_LOWER: return True return False def regexp_valid(data): if PATTERN_VALID.match(CLEAR_WHITESPACE.sub("", data)): return True return False def regexp_valid_strict(data): if PATTERN_STRICT.match(CLEAR_WHITESPACE.sub("", data)): return True return False good.txtstrict.txt,则可以执行以下三种情况:

bad.txt

如果你把每个呼叫计时(所以3个呼叫,每个循环有3个不同的线路),比如100,000个循环你得到:

# open test files and only get the first lines
with open("good.txt", "r") as g, open("strict.txt", "r") as s, open("bad.txt", "r") as b:
    g = g.readline()  # overwrite is perfectly fine for our test
    s = s.readline()  # overwrite is perfectly fine for our test
    b = b.readline()  # overwrite is perfectly fine for our test

# make sure our functions perform adequately
assert string_valid(g) is regexp_valid(g) is True
assert string_valid_strict(g) is regexp_valid_strict(g) is False
assert string_valid(s) is regexp_valid(s) is True
assert string_valid_strict(s) is regexp_valid_strict(s) is True
assert string_valid(b) is regexp_valid(b) is False
assert string_valid_strict(b) is regexp_valid_strict(b) is False

这是正则表达式的最佳案例 - 我们甚至编译了空白删除模式。 OTOH,字符串搜索可以进一步优化(对于非严格的例子,切片而不是Python 2.7.11 string_valid: 100,000 loops: 0.31 s, per loop: 3.15 µs string_valid_strict: 100,000 loops: 0.27 s, per loop: 2.76 µs regexp_valid: 100,000 loops: 1.34 s, per loop: 13.44 µs regexp_valid_strict: 100,000 loops: 1.38 s, per loop: 13.83 µs == Python 3.5.1 string_valid: 100,000 loops: 0.37 s, per loop: 3.73 µs string_valid_strict: 100,000 loops: 0.33 s, per loop: 3.37 µs regexp_valid: 100,000 loops: 1.13 s, per loop: 11.28 µs regexp_valid_strict: 100,000 loops: 1.22 s, per loop: 12.17 µs 等。)。

正则表达式非常棒,但仅在需要时才有效。没有理由使用正则表达式来解决像这样的简单问题。