Compare RPM Packages using Python

半世苍凉 提交于 2019-12-13 04:20:30

问题


I'm trying to compare a csv file containing required Linux packages with the current installed packages. The comparison should output any packages not installed or newer than the current installed packages.

The problem is that I'm unable to loop through the list of installed packages and show all hits, for instance packages with the same name and version, but different architecture should be shown twice(for instance compat-libstdc++-33), but I only getting the first hit with the script below.

#!/usr/bin/python

import rpm
import csv
import sys
import os

'''
Script to check installed rpms against a csv file containing the package name and version similar to the list below:
atk,1.12.2
libart_lgpl,2.3
info,4.9
libsepol,1.15.2
libusb,0.1.12
libfontenc,1.4.2

'''

if len(sys.argv) !=2:
        print ''
        print 'Usage: ', sys.argv[0], '/path/to/csv_input_file'
        print ''
        sys.exit(1)

if not os.path.isfile(sys.argv[1]):
        print ''
        print sys.argv[1], 'not found!'
        print ''
        sys.exit(1)

else:
        input_csv = sys.argv[1]

pkgRequired = csv.reader(open(input_csv),delimiter=',')

pkgInstalledName = []
pkgInstalledVersion = []
pkgInstalledArch = []

ts = rpm.TransactionSet()
mi = ts.dbMatch()

for h in mi:
        pkgInstalledName.append((h['name']))
        pkgInstalledVersion.append((h['version']))
        pkgInstalledArch.append((h['arch']))

for row in pkgRequired:
        pkgRequiredName = row[0]
        pkgRequiredVersion = row[1]
        #pkgRequiredArch = row[2]

        if pkgRequiredName in pkgInstalledName:

                if pkgInstalledVersion[pkgInstalledName.index(pkgRequiredName)] >= pkgRequiredVersion:
                        pass
                else:
                        print '\nInstalled:  ',pkgInstalledName[pkgInstalledName.index(pkgRequiredName)], pkgInstalledVersion[pkgInstalledName.index(pkgRequiredName)], pkgInstalledArch[pkgInstalledName.index(pkgRequiredName)], ' \nRequired: ', ' ', pkgRequiredName,pkgRequiredVersion

回答1:


Assuming that there's no problem with the way that you're reading the list of installed packages (I'm not familiar with the rpm module), then your only problem is with using the index() function. This function return the first occurrence of an item with the specified value - and it isn't what you want.

A correct implementation (which is also much more efficient) would be:

installedPackages = {} #create a hash table, mapping package names to LISTS of installed package versions and architectures
for h in mi: 
  l = installedPackages.get(h['name'], list()) #return either the existing list, or a new one if this is the first time that the name appears.
  l.append( (h['version'], h['arch']) )

...
if requiredPackageName in installedPackages:
  for ver, arch in installedPackages[requiredPackageName]: print ...



回答2:


This is what I ended up doing to get this working. The script currently is not checking for the architecture of required packages, but at least it shows the arch installed. The script works (as far as I know) but can be improved as its my first at python :)

    #!/usr/bin/python

import rpm
import csv
import sys
import os

'''
Script to check installed rpms against a csv file containing the package name and version similar to the list below:
atk,1.12.2
libart_lgpl,2.3
info,4.9
libsepol,1.15.2
libusb,0.1.12
libfontenc,1.4.2

'''

#silverbullet - 20120301

if len(sys.argv) !=2:
        print ''
        print 'Usage: ', sys.argv[0], '/path/to/csv_input_file'
        print ''
        sys.exit(1)

if not os.path.isfile(sys.argv[1]):
        print ''
        print sys.argv[1], 'not found!'
        print ''
        sys.exit(1)

else:
        input_csv = sys.argv[1]

pkgRequired = csv.reader(open(input_csv),delimiter=',')

pkgInstalledName = []
pkgInstalledVersion = []
pkgInstalledArch = []

ts = rpm.TransactionSet()
mi = ts.dbMatch()

for h in mi:
        pkgInstalledName.append((h['name']))
        pkgInstalledVersion.append((h['version']))
        pkgInstalledArch.append((h['arch']))

for row in pkgRequired:
        try:
                pkgRequiredName = row[0]
                pkgRequiredVersion = row[1]
                #pkgRequiredArch = row[2] - This is not implemented yet, ie, script will ignore architecture in csv input file
        except:
                print "Unexpected Error. Check if input is csv format with no blank lines. "#, sys.exc_info()[1]
                break
        else:
                for pos, pkg in enumerate(pkgInstalledName):
                        if pkg == pkgRequiredName:
                                if pkgInstalledVersion[pos] >= pkgRequiredVersion:
                                        pass
                                else:
                                        print '\nInstalled:', pkgInstalledName[pos], pkgInstalledVersion[pos], pkgInstalledArch[pos], '\nRequired: ', pkg, pkgRequiredVersion


来源:https://stackoverflow.com/questions/9380240/compare-rpm-packages-using-python

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!