@uni_Ox: Der Code mit dem `concurrent.futures` macht ja beides, also alles zweimal (beziehungsweise durch einen Fehler im Programm dann doch nicht). Mit dem ``if __name__ …`` und der `main()`-Funktion das ist auch etwas durcheinander. Das macht man ja um das Hauptprogramm von Modulebene in eine Funktion zu bekommen um globale Variablen loszuwerden und das Modul ohne Nebeneffekte importieren zu können. Du hast trotzdem globale Variablen, Programm auf Modulebene, und rufst die `main()` auch noch ausserhalb des ``if __name__ …`` auf.
Eingerückt wird vier Leerzeichen pro Ebene.
`sys` wird importiert, aber nirgends verwendet.
`start` wird zweimal definiert, der erste Wert wird nirgends verwendet.
Funktionen werden üblicherweise nach der Tätigkeit benannt die sie ausführen. `lastuser` wäre ein Name für einen Wert der den letzten Benutzer repräsentiert (mit Unterstrich zwischen den Worten wäre es besser), eine Funktion sollte eher `get_last_user()` oder so ähnlich heissen. Alles was eine Funktion an Werten benötigt sollte die Funktion als Argument betreten und Ergebnisse die Funktion als Rückgabewert verlassen. Insbesondere wenn die Funktion mit einer Funktion wie `map()` verwendet wird, braucht sie einen Rückgabewert, denn sonst macht `map()` keinen Sinn. Das liefert ja die Rückgabewerte von den Aufrufen.
``pass`` macht in einem nichtleeren Block keinen Sinn.
Nun zum Fehler: Du musst die Abfragen nicht nur parallel über den `ThreadPoolExecutor` starten, sondern auch die Ergebnisse verarbeiten. Sonst passiert das parallel solange wie das Hauptprogramm läuft und wird abgebrochen sobald es fertig ist, ohne das Du irgendetwas mit den Ergebnissen gemacht hast. (Die es dafür wie gesagt auch geben muss: also Rückgabewerte von den Aufrufen.)
Ich würde die `max_worker` nicht so stark einschränken wenn man erwartet das die eher blockierend in Kommunikation hängen bleiben. Denn auch bei zweien ist die Chance gross, dass beide auf Daten warten.
``for i in range(len(sequence)):`` und `i` dann als Index in `sequence` zu verwenden ist in Python ein „anti pattern“. Man kann direkt über die Elemente von Sequenztypen iterieren.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python2
from __future__ import absolute_import, division, print_function
import time
from itertools import imap
from concurrent import futures
import wmi
def get_last_user(computer_name):
users = list()
try:
for session in wmi.WMI(computer_name).Win32_LogonSession():
for user in session.references('Win32_LoggedOnUser'):
users.append(user.Antecedent.Caption)
except:
#
# FIXME Just handle specific exception(s) or log exception
# and traceback.
#
users.append('No Access')
return users
def main():
use_executor = True
computer_names = ['pcname1', 'pcname2', 'pcname3']
print('main: starting')
start = time.time()
last_logged_on_users = list()
if use_executor:
#
# TODO Better `max_workers` value.
#
map_function = futures.ThreadPoolExecutor(max_workers=2).map
else:
map_function = imap
for users in map_function(get_last_user, computer_names):
last_logged_on_users.extend(users)
end = time.time()
print(end - start)
if __name__ == '__main__':
main()