2016-11-11 7 views
1

Ich versuche, eine globale Liste zu verwenden, die angehängt werden kann, wenn ein Thread/Prozess eine Aufgabe beendet. Mein Haupt-Thread kann davon lesen, aber durch die Funktion kann es nicht anhängen. Im Grunde mache ich Anfragen, um funktionierende Proxies zu bekommen und versuche dann, sie in der Liste zu speichern und dann die Liste am Ende auszudrucken. Ich habe so viel wie möglich ausgeschnitten.Python 3.5 globale Variable wird nicht anhängen

goodProxyList = ["test"] 


def testProxy(x): 
    global goodProxyList 
    try: 
     test = requests.get('http://someurl.com/', proxies=proxies, timeout=10) 
     if test.status_code == 200: 
      goodProxyList.append(x) 
     else: 
      print("Something went wrong! :/" + " From PID: " + str(pid)) 
    except: 
     print("SOMETHING WENT VERY WRONG" + " From PID: " + str(pid)) 


if __name__ == '__main__': 
    ##Setup Stuff happens 
    p=Pool(2) 
    p.map(testProxy, proxyList) 
    for i in goodProxyList: 
     print(i) 

Auch wenn ich goodProxyList.append (x) zu goodProxyList.append ("Alles"), die letzten 2 Zeilen noch onlt Ausgabe "test" ändern. Was mache ich falsch?

EDIT:

Ich habe die Antwort durch Hilfe von brianpck gefunden. Wie er sagt, scheinen Prozesse anders als Threads zu funktionieren. Mein Wechsel zu einem Pool-Thread funktioniert jetzt einwandfrei.

#p=Pool(2) 
#p.map(testProxy, proxyList) 
with concurrent.futures.ThreadPoolExecutor() as executor: 
    executor.map(testProxy, proxyList) 
+0

Was genau meinen Sie, "kann nicht daran anhängen"? Dies sollte gut funktionieren (und in der Tat ist es nicht einmal notwendig, 'global goodProxyList' explizit zu deklarieren). – brianpck

+0

Sorry, ich hätte sagen sollen, dass die Ausgabe der letzten 2 Zeilen immernoch nur" test "ist und sonst nichts. – user3406647

+0

@brianpck zum Anhängen an eine Variable/Liste außerhalb des Funktionsumfangs müssen Sie 'global goodProxyList' deklarieren. – r0xette

Antwort

0

Die Frage ist hier mit Pool, nicht mit global.

Beim Anhängen an eine Liste (ein veränderbares Objekt) im Funktionsumfang wird die Liste auch im globalen Bereich mutiert. (Tatsächlich müssen Sie nicht einmal das Schlüsselwort global verwenden: Wenn die Funktion die Variable nicht in ihrem eigenen Bereich findet, sucht sie automatisch im globalen Bereich.) Beachten Sie einen kleinen "Gotcha" im folgenden Code , weil map ist ein Generator-ähnliches Objekt:

x = [] 

def add_to_x(i): 
    x.append(i) 

if __name__ == '__main__': 
    y = map(add_to_x, [1, 2]) 
    print(x) # still [] 
    list(y) 
    print(x) # now [1, 2] 

Das folgende einfache Beispiel mit Pool allerdings nicht funktioniert:

from multiprocessing import Pool 

x = [] 

def add_to_x(i): 
    x.append(i) 

if __name__ == '__main__': 
    p = Pool(2) 
    list(p.map(add_to_x, [1, 2])) 
    print(x) # prints [] ! 

Warum? Die Antwort auf Python multiprocessing global variable updates not returned to parent ist aufschluss: hier ist der relevante Teil:

Wenn Sie multiprocessing verwenden, um einen zweiten Prozess zu öffnen, eine völlig neue Instanz von Python, mit einem eigenen globalen Zustand, erstellt wird. Dieser globale Status wird nicht gemeinsam verwendet, sodass Änderungen, die von untergeordneten Prozessen an globalen Variablen vorgenommen werden, für den übergeordneten Prozess unsichtbar sind.

Sie könnten damit auf viele Arten umgehen. Ein Weg wäre, testProxy zu is_good_proxy zu ändern, was einen booleschen Wert zurückgibt. Sie könnten dann die anhängende Logik in der Hauptschleife anwenden.

+0

Ahh sehr interessant. Wenn Sie nicht sagen können, dass ich zum ersten Mal irgendeine Art von Multithreading/Verarbeitung verwende. Könnte dies gelöst werden (und ist es möglich?), Einen Pool von Threads zu verwenden und keine separaten Prozesse? – user3406647

+0

Ich bin mir nicht sicher: Ich hatte auch keine Gelegenheit, 'Multiprocessing' zu verwenden. Es scheint jedoch nicht richtig zu sein, 'map' zu verwenden, wenn Ihr Endziel an eine Liste anknüpft, die Sie bereits haben. – brianpck

+1

Ich habe das Problem gelöst, denke ich.Es scheint, dass Prozesse ihren eigenen globalen Zustand haben, aber Threads nicht? Ich wechselte zu einem Pool Faden durch diese Zeilen hinzufügen und es funktioniert jetzt: # p = Pool (2) # p.map (testProxy, Proxylist) mit concurrent.futures.ThreadPoolExecutor() als Vollstrecker: executor.map (testProxy, ProxyList) – user3406647