2017-06-07 25 views
1

我正在爲工作的項目涉及中插入的文件解析到我們的本地數據庫。爲了編寫有效的健壯代碼,我試圖看看驗證文件的最佳方法。我已經寫了兩個Python腳本:文件驗證在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 :(' 

正如我希望是顯而易見的,我使用的各種格式的簡單字符串字面比較工作,以確保一些安全,以及一純粹依賴於正則表達式的版本。任何人都可以解釋這兩種方法的優缺點嗎?他們都花費相同的時間來執行,並且都是可讀的。我目前看到的唯一優點是使用正則表達式意味着在比較字符串文字之前不需要做太多手動格式化。

+0

對於初學者 - 你爲什麼要讀整個文件只是爲了「驗證」的第一線? – zwer

+0

,因爲經過驗證,假設它是有效的,文件將被讀入。這不是我關心的地方,當然,正確的有效方法是讀取第一行,驗證,然後讀取其餘部分。我是隻對驗證線路本身的優點/缺點感興趣 – Turk

回答

2

假設你沒有看到加載整個文件的問題,假設您解決您的正則表達式(你提出它的程序將打破不匹配,你應該檢查是否有一個匹配,如果不的方式有一組在其內)這兩個是不一樣。考慮你的文件存在的第一行:

PubNo | Name | CoverID | Issue | CustomLabel | Split | SomethingMore 

你的正則表達式「驗證」將迎來它的成功,您的字符串比較不會。如果你希望你的第一列「驗證」精確該字符串,沒有別的匹配,你有你的正則表達式模式更改爲r"\|?PubNo\|Name\|CoverID\|Issue\|CustomLabel\|Split\|?$"。此外,您的正則表達式'驗證程序'將消耗「替換」部分中的所有空白字符,包括製表符,而字符串比較器不會。

所有的事情都是平等的 - 字符串搜索將是大大在這兩種情況下更快 - 這是不計算正則表達式引擎的裝載,準備圖案和所需的所有其他支持結構。即使緩存模式,並刪除了正則表達式的所有缺點,字符串比較仍然會更快。考慮像設置:

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 

這將涵蓋例,這兩種方法(嚴格匹配僅僅是起步)。你沒有考慮建立你的正則表達式忽略空格,這樣你就不需要替換,但也不會大幅加速它(實際上,它可能會比這還慢)。

所以,現在,如果你有3個文件,說是涵蓋所有三種情況下good.txtstrict.txtbad.txt,你可以運行這樣一個特設的測試:

# 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 

如果你的時間爲每個電話那些(所以3個電話,每個循環3條不同的線路)超過,比如說,10圈的你:

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 

這是正則表達式最好的情況下 - 我們甚至編制空白刪除模式。 OTOH,字符串搜索可以進一步優化(對於非嚴格示例,切片代替startswith()等)。

正則表達式很好,但只有在需要的時候。沒有理由利用正則表達式來解決像這樣的簡單問題。