如何修改线程内的列表?

时间:2014-03-05 20:04:25

标签: python linux multithreading

我需要通过在线程末尾添加一些元素来修改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 

最后一个print语句显示一个空列表[]。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

你有一些问题。

  1. 您指定alist为args,但是您需要将其作为一个看起来像您尝试做的元组传递,但是一个项目元组看起来像(alist,)。现在你只是使用alist global,这可能不是你想要的。

  2. 你的go方法不期望参数(即alist)。

  3. 为了保证线程安全,我相信您需要使用某种信号量/互斥锁/锁定原语。线程模块附带一个Lock实现,您可以使用它来限制在追加操作期间对alist的访问。

  4. 最重要的是,在打印结果之前,您不会等待线程完成。要等待线程完成,您需要在线程上调用.join()

  5. 我可能会选择使用另一个Queue实例将结果放入,然后您可以从队列中读取所有内容以在线程完成后构建列表。

    以下是您的代码的更新版本(正常工作)。就像我说的那样,我可能会选择使用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