2016-03-06 71 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的清单。

让我知道这是否有帮助!