Create a set, and use it to discard extra copies.

Documentation

  1. Class set (and the function set) in the Python Standard Library
  2. Sets in the Python Tutorial

The value of each key in the dictionary is None (line 62).

set.py

The output is 44 lines, containly only one copy of Grover Cleveland:

George Washington
John Adams
Thomas Jefferson
James Madison
James Monroe
John Quincy Adams
Andrew Jackson
Martin Van Buren
William Henry Harrison
John Tyler
James K. Polk
Zachary Taylor
Millard Fillmore
Franklin Pierce
James Buchanan
Abrajam Lincoln
Andrew Johnson
Ulysses S. Grant
Rutherford B. Hayes
James A. Garfield
Chester A. Arthur
Grover Cleveland
Benjamin Harrison
William McKinley
Theodore Roosevelt
William Howard Taft
Woodrow Wilson
Warren G. Harding
Calvin Coolidge
Herbert Hoover
Franklin D. Roosevelt
Harry S. Truman
Dwight D. Eisenhower
John F. Kennedy
Lyndon B. Johnson
Richard Nixon
Gerald Ford
Jimmy Carter
Ronald Reagan
George H. W. Bush
Bill Clinton
George W. Bush
Barack Obama
Donald Trump

Things to try

  1. In the above script, replace the dictionary with a set. A set is like a dictionary with keys but no corresponding values. Change
    dictionaryOfPresidents = {}   #Start with an empty dictionary.
    
    for president in listOfPresidents[1:]:             #Skip the dummy item.
        if president not in dictionaryOfPresidents:
            dictionaryOfPresidents[president] = None   #Seeing him for the first time.
            print(president)
    
    to the following. I slapped on the line numbers to make it easy for you to count the lines of output.
    setOfPresidents = set(listOfPresidents[1:])   #Do not include the dummy item.
    
    for i, president in enumerate(setOfPresidents, start = 1):
        print(f"{i:2} {president}")
    

    The order has not been preserved, but the extra copy of Grover Cleveland has been removed. There are only 44 lines of output.

     1 Andrew Johnson
     2 George Washington
     3 Ulysses S. Grant
     4 John Quincy Adams
     5 Chester A. Arthur
     6 Franklin D. Roosevelt
     7 James K. Polk
     8 Grover Cleveland
     9 Thomas Jefferson
    10 Dwight D. Eisenhower
    11 Abraham Lincoln
    12 Andrew Jackson
    13 Zachary Taylor
    14 John Tyler
    15 Theodore Roosevelt
    16 Franklin Pierce
    17 Rutherford B. Hayes
    18 James Monroe
    19 William Howard Taft
    20 Jimmy Carter
    21 James Madison
    22 Gerald Ford
    23 George H. W. Bush
    24 Warren G. Harding
    25 Lyndon B. Johnson
    26 John F. Kennedy
    27 William Henry Harrison
    28 James Buchanan
    29 Martin Van Buren
    30 Herbert Hoover
    31 Woodrow Wilson
    32 James A. Garfield
    33 Harry S. Truman
    34 John Adams
    35 Bill Clinton
    36 Benjamin Harrison
    37 Richard Nixon
    38 Millard Fillmore
    39 George W. Bush
    40 Calvin Coolidge
    41 Ronald Reagan
    42 Barack Obama
    43 Donald Trump
    44 William McKinley
    
  2. The macOS and Linux command ps lists all the current processes (running programs), one per line. The command line option -A stands for “all”; the -o comm stands for “output the name of the command”. Here are the first ten and last ten lines of the output of the ps program. The first line of output, COMM, is a header line. Many of the other lines are pathnames, separated by slashes into components. Some lines (e.g., login, -bash) appear more than once.

    We follow the ps immediately with an echo $? to demonstrate that the ps produced exit status 0. For the $?, see “status of the most recently executed foreground pipeline” in the documentation for the Bourne Again shell bash.

    A similar command in the Microsoft Windows command prompt is tasklist.

    ps -A -o comm
    COMM
    /sbin/launchd
    /usr/libexec/UserEventAgent
    /usr/sbin/syslogd
    /System/Library/PrivateFrameworks/Uninstall.framework/Resources/uninstalld
    /usr/libexec/kextd
    /System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvent
    /System/Library/PrivateFrameworks/MediaRemote.framework/Support/mediaremoted
    /System/Library/CoreServices/appleeventsd
    /usr/libexec/configd
    etc.
    /usr/sbin/spindump
    /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework
    /System/Library/Frameworks/QuickLook.framework/Resources/quicklookd.app/Content
    /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents
    login
    -bash
    ssh
    login
    -bash
    ps
    
    echo $?
    0
    

    The os.popen function in line 10 of ps.py launches the ps program. The Python script is therefore called the parent processs and the ps program is called its child process. ps is at line number 181 in the following output. (Python itself is line 41, and my bash shell is line 1.) os.popen also opens a pipe that carries data (in this case, lines of text) from the child process to the parent process.

    ps.py

      1 -bash
      2 AirPlayUIAgent
      3 AirPlayXPCHelper
      4 AlertNotificationService
      5 AppleCameraAssistant
      6 AppleIDAuthAgent
      7 AppleSpell
      8 AssetCache
      9 AssetCacheLocatorService
     10 CVMServer
     11 CalNCService
     12 CalendarAgent
     13 CallHistoryPluginHelper
     14 CallHistorySyncHelper
     15 CloudKeychainProxy
     16 CommCenter
     17 ContactsAccountsService
     18 ContactsAgent
     19 ContainerMetadataExtractor
     20 CoreLocationAgent
     21 CrashReporterSupportHelper
     22 DataDetectorsSourceAccess
     23 Dock
     24 DuetHeuristic-BM
     25 EscrowSecurityAlert
     26 Finder
     27 FolderActionsDispatcher
     28 Google Chrome
     29 Google Chrome Helper
     30 IDLE
     31 IMDPersistenceAgent
     32 IMRemoteURLConnectionAgent
     33 KernelEventAgent
     34 KeychainSyncingOverIDSProxy
     35 KiesAgent
     36 LaterAgent
     37 LookupViewService
     38 NotificationCenter
     39 PAH_Extension
     40 ProtectedCloudKeySyncing
     41 Python
     42 SafariCloudHistoryPushAgent
     43 ScopedBookmarkAgent
     44 Siri
     45 SocialPushAgent
     46 Spotlight
     47 SubmitDiagInfo
     48 SystemUIServer
     49 TISwitcher
     50 TMCacheDelete
     51 Terminal
     52 USBAgent
     53 UserEventAgent
     54 VDCAssistant
     55 VTDecoderXPCService
     56 ViewBridgeAuxiliary
     57 WiFiAgent
     58 WiFiProxy
     59 WiFiVelocityAgent
     60 WindowServer
     61 WirelessRadioManagerd
     62 accountsd
     63 airportd
     64 akd
     65 amfid
     66 appleeventsd
     67 apsd
     68 askpermissiond
     69 aslmanager
     70 assistant_service
     71 assistantd
     72 authd
     73 autofsd
     74 awdd
     75 bird
     76 blued
     77 callservicesd
     78 captiveagent
     79 cdpd
     80 cfprefsd
     81 cloudd
     82 cloudpaird
     83 cloudphotosd
     84 com.apple.AmbientDisplayAgent
     85 com.apple.CloudPhotosConfiguration
     86 com.apple.CodeSigningHelper
     87 com.apple.CommerceKit.TransactionService
     88 com.apple.DictionaryServiceHelper
     89 com.apple.GSSCred
     90 com.apple.PerformanceAnalysis.animationperfd
     91 com.apple.PhotoIngestService
     92 com.apple.audio.DriverHelper
     93 com.apple.audio.SandboxHelper
     94 com.apple.ctkpcscd
     95 com.apple.dock.extra
     96 com.apple.geod
     97 com.apple.iTunesLibraryService
     98 com.apple.ifdreader
     99 com.apple.notificationcenterui.WeatherSummary
    100 com.apple.photomoments
    101 com.apple.quicklook.ThumbnailsAgent
    102 com.apple.sbd
    103 com.apple.speech.speechsynthesisd
    104 configd
    105 coreaudiod
    106 coreauthd
    107 corebrightnessd
    108 coreduetd
    109 coreservicesd
    110 corestoraged
    111 coresymbolicationd
    112 crashpad_handler
    113 ctkahp
    114 ctkd
    115 deleted
    116 diagnostics_agent
    117 diskarbitrationd
    118 diskspaced
    119 displaypolicyd
    120 distnoted
    121 filecoordinationd
    122 findmydeviced
    123 fmfd
    124 followupd
    125 fontd
    126 fseventsd
    127 fuspredownloader
    128 gamecontrollerd
    129 gamed
    130 geodMachServiceBridge
    131 hidd
    132 iTunesHelper
    133 icdd
    134 iconservicesagent
    135 iconservicesd
    136 identityservicesd
    137 imagent
    138 imklaunchagent
    139 installd
    140 installerdiagd
    141 kextd
    142 keyboardservicesd
    143 launchd
    144 launchservicesd
    145 locationd
    146 logd
    147 login
    148 logind
    149 loginwindow
    150 lsd
    151 mDNSResponder
    152 mDNSResponderHelper
    153 mapspushd
    154 mdflagwriter
    155 mds
    156 mds_stores
    157 mdworker
    158 media-indexer
    159 mediaremoteagent
    160 mediaremoted
    161 mobileassetd
    162 nbagent
    163 nbstated
    164 nehelper
    165 netbiosd
    166 networkserviceproxy
    167 notifyd
    168 nsurlsessiond
    169 nsurlstoraged
    170 ntpd
    171 opendirectoryd
    172 parsecd
    173 passd
    174 pboard
    175 pbs
    176 periodic-wrapper
    177 photoanalysisd
    178 photolibraryd
    179 pkd
    180 powerd
    181 ps
    182 quicklookd
    183 revisiond
    184 sandboxd
    185 secd
    186 secinitd
    187 securityd
    188 securityd_service
    189 sharedfilelistd
    190 sharingd
    191 soagent
    192 softwareupdate_notify_agent
    193 softwareupdated
    194 spindump
    195 spindump_agent
    196 ssh
    197 ssh-agent
    198 storeaccountd
    199 storeassetd
    200 storedownloadd
    201 storeinstalld
    202 storelegacy
    203 suggestd
    204 suhelperd
    205 symptomsd
    206 syslogd
    207 sysmond
    208 syspolicyd
    209 system_installd
    210 systemsoundserverd
    211 systemstats
    212 taskgated
    213 tccd
    214 thermald
    215 trustd
    216 uninstalld
    217 usbd
    218 usbmuxd
    219 useractivityd
    220 usernoted
    221 videosubscriptionsd
    222 warmd
    223 watchdogd
    224 wdhelper
    225 wifivelocityd
    226 wirelessproxd
    
  3. ps produces exit status 1 if you misspell comm.
    ps -A -o komm
    ps: komm: keyword not found
    ps: no valid keywords; valid keywords:
    %cpu %mem acflag acflg args blocked caught comm command cpu cputime etime f
    flags gid group ignored inblk inblock jobc ktrace ktracep lim login logname
    lstart majflt minflt msgrcv msgsnd ni nice nivcsw nsignals nsigs nswap nvcsw
    nwchan oublk oublock p_ru paddr pagein pcpu pending pgid pid pmem ppid pri
    pstime putime re rgid rgroup rss ruid ruser sess sig sigmask sl start stat
    state stime svgid svuid tdev time tpgid tsess tsiz tt tty ucomm uid upr user
    usrpri utime vsize vsz wchan wq wqb wql wqr xstat
    
    echo $?
    1
    
    If the child process’s exit status is not zero, the close method returns the child process’s exit status multiplied by 256 on macOS and Linux. (See “left-shifted by one byte” in the os.popen documentation.) There is no multiplication on Microsoft Windows. (In Microsoft Windows, the exit status is called the %errorlevel%.)
    infile = os.popen("ps -A -o komm")   #Create a child process and a pipe.
    
    "ps -A -o komm" produced exit status 1.
    
  4. Change the list comprehension in line 22
    lines = [line.rsplit("/", maxsplit = 1)[-1] for line in lines]
    
    to
    lines = [os.path.basename(line) for line in lines]
    
    to eliminate an operating system dependency (macOS and Linux "/" vs. Microsoft Windows "\\").
  5. The first line of output is -bash, because the ASCII code of a dash (hexadecimal 2D) is less than the ASCII code of any letter. See the ASCII code numbers in For. (For the dash, see the “hyphen” in login, far beyond the scope of this course.) Let’s ignore a leading dash when we sort the names. Change
    lines = sorted(lines)
    
    in line 23 to
    def score(line):
        "Strip a leading dash from line."
        return line.lstrip("-")
    
    lines = sorted(lines, key = score)
    
    or to
    lines = sorted(lines, key = lambda line: line.lstrip("-"))
    
     73 autofsd
     74 awdd
     75 -bash
     76 bird
     77 blued
    
  6. Want to make your code harder to read?
  7. infile = os.popen("ps -A -o comm")
    
    for i, line in enumerate(sorted(
        [os.path.basename(line) for line in set(infile.read().splitlines()[1:])],
        key = lambda line: line.lstrip("-")), start = 1):
    
        print(f"{i:3} {line}")
    
  8. The same Python script in Microsoft Windows:
    import sys
    import os
    import csv
    
    infile = os.popen("tasklist /fo csv /nh")  #format CSV, no header
    lines = csv.reader(infile)
    lines = sorted(set([line[0] for line in lines]))
    
    status = infile.close()
    if status != None:
        print("status =", status)   #this is the Microsoft %errorlevel%
        sys.exit(1)
    
    for i, line in enumerate(lines, start = 1):
        print(f"{i:3} {level}")
    
    sys.exit(0)