简体   繁体   English

如何修改线程内的列表?

[英]How do I modify a list inside a thread?

I need to modify a list by adding some elements at the end from a thread. 我需要通过在线程的末尾添加一些元素来修改list

This is my code: 这是我的代码:

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 

The last print statement display an empty list, [] . 最后一个打印语句显示一个空列表[] Any ideas? 有任何想法吗?

You have a few problems. 你有几个问题。

  1. You specify alist as the args, but you need to pass it as a tuple which it looks like you tried to do, but a one item tuple would look like this (alist,) . 您可以将alist指定为args,但需要将其作为一个元组传递,看起来像您尝试这样做,但是一个元组看起来像这样(alist,) Right now you are just using the alist global which is likely not what you want. 现在,您只是使用全局列表,这可能不是您想要的。

  2. Your go method does not expect an argument (namely, the alist). 您的go方法不需要参数(即alist)。

  3. To be thread safe, I believe you will need to use some sort of semaphore/mutex/lock primitive. 为了线程安全,我相信您将需要使用某种信号量/互斥量/锁原语。 The threading module comes with a Lock implementation which you can use to restrict access to alist during the append operation. threading模块带有您可以使用来限制访问Lock实现alist追加操作过程中。

  4. Most importantly, you are not waiting for your threads to finish before you print the result. 最重要的是,在打印结果之前,您不必等待线程完成。 To wait for thread to finish you need to call .join() on the thread. 要等待线程完成,您需要在线程上调用.join()

I would probably opt for using another Queue instance to put the results into, then you could read all from the queue to construct your list once the threads are complete. 我可能会选择使用另一个Queue实例将结果放入,然后在线程完成后就可以从队列中读取所有内容以构造列表。

Here is an updated version (working) of your code. 这是您代码的更新版本(有效)。 Like I said, I would probably opt to use a Queue instead, and I have not used the threading module much since I switched to eventlet/gevent... so there may be ways to improve on what I provided. 就像我说的那样,我可能会选择使用Queue,并且自从我切换到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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM