如何在线程中修改列表?
我需要在一个 list
的末尾添加一些元素,这个操作是在一个线程中进行的。
这是我的代码:
def go():
while queueCommand.qsize() > 0:
command = queueCommand.get(False)
res = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True)
output = res.communicate()
output = str(output)
star = output.find("address") + 8
en = output.find(",")
ip = output[star:en-3]
alist.append(ip) #<================== her i use the liste
if __name__ == '__main__':
with open ("icq.txt","r") as myfile:
text = myfile.read()
end = 0
alist = []
queueCommand = Queue.Queue()
while True:
start = text.find("href=") + 13
if start == 12:
break
end = text.find("/",start)
if text[start:end].find("icq.com") != -1:
hostname="host "+ text[start:end]
queueCommand.put(hostname)
text = text[end:len(text)]
for i in range(10):
threading.Thread(target=go,args=(alist)).start() #<====== i give the list as argument
print alist
最后的打印语句显示的是一个空列表,[]
。有什么想法吗?
1 个回答
2
你遇到了一些问题。
你把
alist
作为参数传入,但其实你需要把它作为一个元组传递,看起来你是想这么做的,但一个只有一个元素的元组应该是这样写的(alist,)
。现在你只是用了全局的 alist,这可能不是你想要的。你的 go 方法并不期待有参数(也就是 alist)。
为了确保线程安全,我认为你需要使用某种信号量、互斥锁或锁机制。线程模块里有一个 Lock 的实现,你可以用它来限制在添加元素到
alist
时的访问。最重要的是,你没有等线程完成就打印结果。要等线程完成,你需要在线程上调用
.join()
。
我可能会选择使用另一个队列实例来存放结果,这样在所有线程完成后,你可以从队列中读取所有结果来构建你的列表。
这是你代码的一个更新版本(可以正常工作的)。就像我说的,我可能会选择使用队列,而且自从我转向使用 eventlet/gevent 后,我对线程模块的使用不多……所以我提供的内容可能还有改进的空间。
import threading
import Queue
import subprocess
lock = threading.Lock()
def go(alist):
while queueCommand.qsize() > 0:
command = queueCommand.get(False)
res = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True)
output = res.communicate()
output = str(output)
star = output.find("address") + 8
en = output.find(",")
ip = output[star:en-3]
lock.acquire()
alist.append(ip) #<================== her i use the liste
lock.release()
def foo(alist):
alist.append("bar")
if __name__ == '__main__':
with open ("icq.txt","r") as myfile:
text = myfile.read()
end = 0
alist = []
queueCommand = Queue.Queue()
while True:
start = text.find("href=") + 13
if start == 12:
break
end = text.find("/",start)
if text[start:end].find("icq.com") != -1:
hostname="host "+ text[start:end]
queueCommand.put(hostname)
text = text[end:len(text)]
threads = []
for i in range(10):
thread = threading.Thread(target=go,args=(alist,)) #<====== i give the list as argument)
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
print alist