2016-03-06 65 views
0

我有以下代碼:如何比較兩個CSV文件在Python 3 - 模塊格式 -

import csv 
import subprocess 

from subprocess import check_output 

# Writing the pacman command output to file in csv format 

sysApps = check_output(["pacman", "-Qn"]) 
sysAppsCSV = csv.DictReader(sysApps.decode('ascii').splitlines(), 
         delimiter=' ', skipinitialspace=True, 
         fieldnames=[ 'name', 'version']) # Thanks to https://stackoverflow.com/a/8880768/5565713 jcollado 

with open('pacman.csv', 'w') as csvfile: 
    rows_sys = csv.writer(csvfile) 
    rows_sys.writerow(sysAppsCSV) 

# Writing the pip command output in csv format 

pipApps = check_output(["pip", "list"]) 
pipAppsCSV = csv.DictReader(pipApps.decode('ascii').splitlines(), 
         delimiter=' ', skipinitialspace=True, 
         fieldnames=[ 'name', 'version']) # Thanks to https://stackoverflow.com/a/8880768/5565713 jcollado 

with open('pip.csv', 'w') as csvfile: 
    rows_pip = csv.writer(csvfile) 
    rows_pip.writerow(pipAppsCSV) 

# Comparing the files 

我要比較兩個文件,不是必需的文件,也可以是變量的內容已經創建,並從pip.csv文件得到結果作爲差異,實際上我想知道什麼是pip.csv而不是pacman.csvhere的例子不適用於我的情況,但我會通過列出名稱和版本以類似的方式輸出結果。

編輯: @Greg Sadetsky感謝您的建議我用你的例子來簡化我的代碼,但不能解決我的問題,我不能以這種方式比較列表。我取得了一些進展,但我仍然沒有得到期望的輸出:

import csv 
import subprocess 

from subprocess import check_output 

#Initializing variables 

results_sys = "" 
results_pip = "" 

# Running the linux commands 

sys_apps = set(check_output(["pacman", "-Qn"]).splitlines()) 
pip_apps = set(check_output(["pip", "list"]).splitlines()) 

# Saving the outputs of the commands in to a CSV format 

for row in sys_apps: 
    result = row.decode('ascii').split(sep=" ") 
    with open('pacman.csv', 'a') as csvfile: 
     rows_sys = csv.writer(csvfile) 
     rows_sys.writerow(result) 

for row in pip_apps: 
    result = row.decode('ascii').split(sep=" ") 
    with open('pip.csv', 'a') as csvfile: 
     rows_sys = csv.writer(csvfile) 
     rows_sys.writerow(result) 

# Opening the files and comparing the results 

with open('pacman.csv', 'r') as pacmanCSV: 
    sys_apps = pacmanCSV.readlines() 
    for row in sys_apps: 
     apps = row.split(",") 
     results_sys = results_sys + " " + apps[0] 

with open('pip.csv', 'r') as pipCSV: 
    pip_apps = pipCSV.readlines() 
    for row in pip_apps: 
     apps = row.split(",") 
     results_pip = results_pip + " " + apps[0] 


results_final = "List of apps installed from pip:\n################################" 
for val in results_pip: 
    if val not in results_sys: 
     results_final = results_final + "\n" + val 


print(results_final) 

當我運行這段代碼,我得到一些大寫字母,例如:Imgur

cropped version

確定,所以後閱讀有關集我做到了這一點:

r1 = set(results_pip) 
r2 = set(results_sys) 

print(r1 - r2) 

但我得到了類似的結果,只有大寫字母的第一個字母出現。

+0

http://stackoverflow.com/questions/15864641/python-difflib-comparing-files http://stackoverflow.com/questions/977491/comparing-2-txt-files-using-difflib-in-python – Sam

+0

問題是'results_sys'和'results_pip'都是你連續追加字符串的字符串(即'results_sys +「」+ apps [0]')。如果你在'for results_pip'中的val中迭代字符串,那麼你將一個一個遍歷字符串中的字母......這不是你想要做的。我將用您的新版本的解決方案編輯我的答案 –

回答

1

您可以使用sets比較兩個軟件包列表,並輕鬆弄清楚哪些軟件包在一個列表中,而另一個列表中沒有。

您是否絕對需要瀏覽CSV文件?你只是在尋找pacmacpip之間的輸出差異嗎?如果是這樣,我在下面創建了一個更簡單的例子。

注意:我的機器上沒有pacman,但我想它的輸出格式與pip類似。如果沒有,你必須調整代碼。

from subprocess import check_output 

sys_apps = set(check_output(["pacman", "-Qn"]).splitlines()) 
pip_apps = set(check_output(["pip", "list"]).splitlines()) 

# show packages present in sys_apps that are absent from pip_apps 
print sys_apps - pip_apps 

編輯:

1爲什麼要通過編寫CSV文件的麻煩,然後讀回,然後只比較集?爲什麼不簡單檢查sys_appspip_apps之間的區別?我假設你需要寫入CSV文件,並且你需要從這些文件中讀回來,然後比較它們的內容。我看到你在混合使用Python 2和Python 3代碼(你有一個「sep」參數來分割,但是你也在調用一個字符串的「decode」)。你正在使用哪個版本的Python?

3-我發現你已經改變了你的代碼了。正如我在對你的問題的評論中解釋的那樣,通過做for val in results_pip你正在迭代該字符串的字符,這可能不是你想要做的(你可能想迭代列表中的元素)。

我將只發布您的代碼的下半部分的另一個版本:

# Opening the files and comparing the results 

with open('pacman.csv', 'r') as pacmanCSV: 
    sys_apps = pacmanCSV.readlines() 

with open('pip.csv', 'r') as pipCSV: 
    pip_apps = pipCSV.readlines() 

print "List of apps installed from pip:\n################################" 

print set(pip_apps) - set(sys_apps) 

正如你所看到的,我不是分裂的逗號從CSV文件中的行,因爲你可以比較充分包名(包括版本)(我認爲檢查是否通過pip安裝了不同版本的軟件包會很重要)。如果你絕對要比較的包名只(而不是版本),你可以在兩個with塊更改爲以下:

with open('pacman.csv', 'r') as pacmanCSV: 
    sys_apps = [app.split(',')[0] for app in pacmanCSV.readlines()] 

with open('pip.csv', 'r') as pipCSV: 
    pip_apps = [app.split(',')[0] for app in pipCSV.readlines()] 

這種提取使用分離的包名,然後保持軟件包名稱而已,並建立一個所有包裹變成sys_appspip_apps的清單。

讓我知道這是否有幫助!