2014-07-18 29 views
3

将导入/使用任何python的内置库产生线程而不被明确询问?是否有任何python内置模块使用线程?

+1

在导入时创建线程应该很少;进口时产生的副作用通常被忽视。但是,似乎'import tkinter'在我的OS X机器上创建了一个新的线程。 –

+3

当然''进口反引力'开始一个新的*进程*! (如果您的网络浏览器尚未运行。) –

回答

7

multiprocessing模块和subprocess模块都在内部产生threading.Thead对象以帮助处理它们产生的进程的I/O。

具体来说,multiprocessing.Poolspawns three threads只要你实例化它:

class Pool(object): 
    ''' 
    Class which supports an async version of the `apply()` builtin 
    ''' 
    Process = Process 

    def __init__(self, processes=None, initializer=None, initargs=(), 
       maxtasksperchild=None): 

     ... # Stuff we don't care about 
     self._worker_handler = threading.Thread(
      target=Pool._handle_workers, 
      args=(self,) 
      ) 
     self._worker_handler.daemon = True 
     self._worker_handler._state = RUN 
     self._worker_handler.start() 


     self._task_handler = threading.Thread(
      target=Pool._handle_tasks, 
      args=(self._taskqueue, self._quick_put, self._outqueue, self._pool) 
      ) 
     self._task_handler.daemon = True 
     self._task_handler._state = RUN 
     self._task_handler.start() 

     self._result_handler = threading.Thread(
      target=Pool._handle_results, 
      args=(self._outqueue, self._quick_get, self._cache) 
      ) 
     self._result_handler.daemon = True 
     self._result_handler._state = RUN 
     self._result_handler.start() 

subprocess生成线程when you call popen_object.communicate,从运行子读取标准输出/标准错误。

def _communicate(self, input): 
    stdout = None # Return 
    stderr = None # Return 

    if self.stdout: 
     stdout = [] 
     stdout_thread = threading.Thread(target=self._readerthread, 
             args=(self.stdout, stdout)) 
     stdout_thread.setDaemon(True) 
     stdout_thread.start() 
    if self.stderr: 
     stderr = [] 
     stderr_thread = threading.Thread(target=self._readerthread, 
             args=(self.stderr, stderr)) 
     stderr_thread.setDaemon(True) 
     stderr_thread.start() 

编辑

Mark Dickinson points outconcurrent.futures.ProcessPoolExecutor还产生一个线程,为类似于multiprocessing.Pool原因(处理I/O与产卵过程):

def _start_queue_management_thread(self): 
    # When the executor gets lost, the weakref callback will wake up 
    # the queue management thread. 
    def weakref_cb(_, q=self._result_queue): 
     q.put(None) 
    if self._queue_management_thread is None: 
     # Start the processes so that their sentinels are known. 
     self._adjust_process_count() 
     self._queue_management_thread = threading.Thread(
       target=_queue_management_worker, 
       args=(weakref.ref(self, weakref_cb), 
         self._processes, 
         self._pending_work_items, 
         self._work_ids, 
         self._call_queue, 
         self._result_queue)) 
     self._queue_management_thread.daemon = True 
     self._queue_management_thread.start() 
+0

对于Python 3,'concurrent.futures'和'asyncio'可能值得一提。 –

+0

@MarkDickinson就我所知,使用'concurrent.futures'你总是明确地要求一个线程(例如使用'ThreadExecutor')。我不认为'asyncio'创建任何线程;它只是有能力与'concurrent.futures.ThreadExecutor'集成。当您没有明确询问时,OP专门寻找使用线程的地方。 – dano

+1

是的,我想这取决于“明确”是如何明确的。一个带有'concurrent.futures'的稍微隐藏的例子就是创建一个'ProcessPoolExecutor':当你第一次向它提交一个工作时,你会在你的主进程中得到一些额外的线程(这要感谢你使用'multiprocessing'机制已经确定,所以也许这不算)。同意'asyncio'。 –

5

下列模块进口threading,表示可以使用“线程”(无论是隐式还是明示)

  1. asyncio
  2. decimal
  3. functools
  4. cookiejar
  5. multiprocessing
  6. queue
  7. sched
  8. subprocess
  9. telnetlib
  10. tempfile
  11. trace

方法论

grep -r "thread" * | grep "import" | grep -v "test" | grep -v "Lib/threading" 

{python install path}/Lib目录。

使用的方法是查看grep结果中是否出现“线程”,并使用一系列grep来处理结果。

所以拿一点盐的这个答案。

+0

是的,其中大部分只是导入它来获得同步原语。我认为唯一一个实际产生的线程在我的回答中没有提到,它是'telnetlib',它使用'thread.start_new_thread'而不是'threading'模块。但是只有在你明确地用'mt_interact'(意思是多线程交互)来提问的时候才会这样做。 – dano

相关问题