Finding unique/obsolete binary Debian packages I have a script I use to prune packages that have gone stale from my custom Debian repository (i.e. they no longer exists on any of the official repositories):

import apt_pkg
import gzip
import subprocess


CUSTOM_REPO = ("/home/tshepang/.custom_repo/dists/tshepang/main/"
               "binary-amd64/Packages.gz")
TEMPLATE = ("/var/lib/apt/lists/http.debian.net_debian_dists_{}_{}_"
            "binary-amd64_Packages")
CODENAMES = 'jessie sid experimental'.split()
ARCHIVE_AREAS = "main contrib non-free".split()


def main():
    custom_repo = apt_pkg.TagFile(gzip.open(CUSTOM_REPO))
    wheezy_packages = list()
    for codename in CODENAMES:
        for archive_area in ARCHIVE_AREAS:
            repo = TEMPLATE.format(codename, archive_area)
            repo = apt_pkg.TagFile(gzip.open(repo, "rb"))
            wheezy_packages.extend([pkg["Package"] for pkg in repo])
    for package in custom_repo:
        package_name = package["Package"]
        if package_name not in wheezy_packages:
            cmd = "apt-cache policy " + package_name
            subprocess.call(cmd.split())
            choice = raw_input("remove from cache [Y/n]? ")
            if not choice or choice.lower().startswith("y"):
                cmd = ("reprepro -vv --basedir /home/tshepang/.custom_repo/ "
                       "remove tshepang " + package_name)
                subprocess.call(cmd.split())

if __name__ == "__main__":
    main()


I strongly suspect the code can be better.

As a sidenote, here is sample UI:




apache2.2-common:
      Installed: (none)
      Candidate: 2.2.22-13
      Version table:
         2.2.22-13 0
            500 file:/home/tshepang/.custom_repo/ tshepang/main amd64 Packages
    remove from cache [Y/n]? 
    removing 'apache2.2-common' from 'tshepang|main|amd64'...
    Exporting indices...
    Deleting files no longer referenced...
    deleting and forgetting pool/main/a/apache2/apache2.2-common_2.2.22-13_amd64.deb
Your code looks very good, so I'll just propose some minor (and subjective) improvements:


Imports: PEP8 has some recommendations about grouping imports that sound pretty reasonable.
("s1" "s2"): I don't know what the orthodoxy says, but I prefer an explicit + in between.
list(): Why not []?
wheezy_packages.extend([pkg["Package"] for pkg in repo]) -> wheezy_packages.extend(pkg["Package"] for pkg in repo).
repo = a, then repo = f(repo). IMHO this is as common a pattern as is undesirable. Different values deserve different variable names (key point of functional programming).
Function too long: I'd split the code in at least two auxiliary functions, one to get wheezy_packages and another to run the commands.