Что такое поток python

У меня есть несколько вопросов, касающихся потоков Python.

  1. Является ли поток Python реализацией Python или ОС?
  2. Когда я использую htop, многопоточный скрипт имеет несколько записей – одинаковое потребление памяти, ту же команду, но другой PID. Означает ли это, что поток [Python] на самом деле является особым видом процесса? (Я знаю, что есть параметр в htop, чтобы показать эти потоки как один процесс – Hide userland threads )
  3. Документация гласит:

Поток может быть помечен как «поток демона». Значение этого флага заключается в том, что вся программа Python завершается, когда остаются только потоки демона.

Моя интерпретация / понимание: основной поток завершается, когда все не-демонные потоки завершаются.

Таким образом, потоки daemon python не являются частью программы Python, если «вся программа Python завершается, когда остаются только потоки демона»?

3 Solutions collect form web for “Что такое поток python”

  1. Нить Python реализована с использованием потоков ОС во всей реализации, которую я знаю (C Python, PyPy и Jython). Для каждого потока Python существует основной поток ОС.

  2. Некоторые операционные системы (один из них Linux) предоставляют все разные потоки, запущенные одним и тем же исполняемым файлом в списке всех запущенных процессов. Это деталь реализации ОС, а не Python. В некоторых других операционных системах вы можете не видеть этот поток при перечислении всех процессов.

  3. Процесс завершится, когда закончится последний не-демонный поток. В этот момент весь поток демона будет завершен. Таким образом, эти потоки являются частью вашего процесса, но не препятствуют его прекращению (в то время как регулярный поток предотвратит его). Это реализовано в чистом Python. Процесс завершается, когда вызывается функция _exit (она будет убивать все потоки), и когда основной поток завершается (или вызывается sys.exit ), интерпретатор Python проверяет, есть ли другой поток не-демона. Если нет, тогда он вызывает _exit , в противном случае он ожидает завершения потоков, отличных от daemon.


Флаг потока демона реализован в чистом Python модулем threading передачи. Когда модуль загружен, объект Thread создается для представления основного потока, и метод _exitfunc регистрируется как крюк atexit .

Код этой функции:

 class _MainThread(Thread): def _exitfunc(self): self._Thread__stop() t = _pickSomeNonDaemonThread() if t: if __debug__: self._note("%s: waiting for other threads", self) while t: t.join() t = _pickSomeNonDaemonThread() if __debug__: self._note("%s: exiting", self) self._Thread__delete() 

Эта функция будет вызываться интерпретатором Python при вызове sys.exit или при завершении основного потока. Когда функция возвращается, интерпретатор вызовет функцию _exit системы. И функция будет завершена, если есть только, если есть, потоки демонов.

Когда вызывается функция _exit , ОС завершает все потоки процесса, а затем завершает процесс. Время выполнения Python не будет вызывать функцию _exit до тех пор, пока не будет выполнен весь поток без демона.

Весь поток является частью процесса.


Моя интерпретация / понимание: основной поток завершается, когда все не-демонные потоки завершаются.

Таким образом, потоки демона python не являются частью программы python, если «вся программа Python завершается, когда остаются только потоки демона»?

Ваше понимание неверно. Для ОС процесс состоит из множества потоков, каждый из которых равен (нет ничего особенного в основном потоке для ОС, за исключением того, что C runtime добавляет вызов _exit в конце main функции). И ОС не знает о потоке демона. Это чисто концепция Python.

В интерпретаторе Python используется собственный поток для реализации потока Python, но помните список каждого созданного потока. И используя его atexit hook, он гарантирует, что функция _exit вернется в ОС только тогда, когда последний поток не-daemon завершится. При использовании «всей программы Python» документация относится ко всему процессу.


Следующая программа может помочь понять разницу между потоком демона и регулярным потоком:

 import sys import time import threading class WorkerThread(threading.Thread): def run(self): while True: print 'Working hard' time.sleep(0.5) def main(args): use_daemon = False for arg in args: if arg == '--use_daemon': use_daemon = True worker = WorkerThread() worker.setDaemon(use_daemon) worker.start() time.sleep(1) sys.exit(0) if __name__ == '__main__': main(sys.argv[1:]) 

Если вы выполните эту программу с помощью «-use_daemon», вы увидите, что программа будет печатать только небольшое количество Working hard строк. Без этого флага программа не будет завершена даже при завершении основного потока, и программа будет печатать Working hard строки до тех пор, пока они не будут убиты.

Я не знаком с реализацией, поэтому давайте сделаем эксперимент:

 import threading import time def target(): while True: print 'Thread working...' time.sleep(5) NUM_THREADS = 5 for i in range(NUM_THREADS): thread = threading.Thread(target=target) thread.start() 
  1. Количество потоков, сообщаемых с помощью ps -o cmd,nlwp <pid> равно NUM_THREADS+1 (еще один для основного потока), поэтому, если инструменты ОС обнаруживают количество потоков, они должны быть потоками ОС. Я пробовал оба с cpython и jython, и, несмотря на то, что в jython есть несколько других потоков, для каждого добавочного потока, который я добавляю, ps увеличивает количество потоков на единицу.

  2. Я не уверен в поведении htop , но ps кажется последовательным.

  3. Я добавил следующую строку перед началом потоков:

     thread.daemon = True 

    Когда я выполнил использование cpython, программа завершилась почти сразу, и процесс не был найден с использованием ps , поэтому я предполагаю, что программа завершена вместе с потоками. В jython программа работала одинаково (она не прерывалась), поэтому, возможно, есть некоторые другие потоки из jvm, которые не позволяют потокам программы завершить работу или потоки демона.

Примечание. Я использовал Ubuntu 11.10 с python 2.7.2+ и jython 2.2.1 на java1.6.0_23

  1. Потоки Python – это практически реализация интерпретатора, потому что так называемый глобальный блокиратор интерпретатора (GIL), даже если он технически использует механизмы потоковой передачи уровня os. На * nix он использует pthreads, но GIL effectivly делает его гибридом, прилипшим к парадигме потоков на уровне приложений. Таким образом, вы увидите его в системах * nix несколько раз в выводе ps / top, но он по-прежнему ведет себя (по производительности), как реализованный программным потоком.

  2. Нет, вы просто видите, как происходит реализация базовых потоков ваших os. Такое поведение проявляется в потоке nix pthread-like или im, хотя даже окна действительно реализуют потоки таким образом.

  3. Когда ваша программа закрывается, она ждет завершения всех потоков. Если у вас есть потоки, которые могут отложить выход неопределенно, может быть разумным отметить эти потоки как «демоны» и позволить вашей программе закончить, даже если эти потоки все еще работают.

Некоторые справочные материалы, которые могут вас заинтересовать:

  • Linux Gazette: Понимание Threading в Python .
  • Дуг Хеллман: методы многократной обработки в Python
  • Дэвид Бэзли: PyCon 2010: понимание Python GIL (видео-презентация)
  • Как обрабатывать asyncore внутри класса в python, не блокируя ничего?
  • Неустранимая ошибка Python и `BufferedWriter`
  • Разрешено ли ведение журнала вне определения функции?
  • Python threading - как получить родительский идентификатор / имя
  • PyQt4 Подождите в потоке для ввода пользователем из GUI
  • Передать аргументы ключевого слова целевой функции в потоке Python.
  • почему мой многопоточный код тратит больше времени, чем однопоточный код
  • Параллельные вызовы базы данных pandas pyodbc SQL
  • Как установить ограничение памяти для потока или процесса в python?
  • wxPython: Threading GUI -> Использование специального обработчика событий
  • Проверьте, жив ли главный поток из другого потока
  •  
    Interesting Posts for Van-Lav

    Конкатенация строки Python – конкатенация '\ n'

    Хороший способ получить кодировку / кодировку ответа HTTP в Python

    Преобразование ndarray из float64 в integer

    Динамическое программирование для примитивного калькулятора

    Ненужный срез произвольных размеров

    Отображение 3 гистограмм на 1 оси четким способом – matplotlib

    Я получаю IndentationError. Как это исправить?

    Flask, как вернуть код статуса успеха для вызова ajax

    Как использовать регулярное выражение python для замены с помощью захваченной группы?

    Извлечение элементов из файла XML с использованием Python

    Как проверить одно и то же утверждение для большого количества данных

    суммирование элементов в вложенном словаре с разными ключами

    Каков новейший способ разработки апплетов панели gnome (с использованием python)

    Как удалить все escape-последовательности из списка строк?

    Как преобразовать numpy datetime64 в datetime

    Python - лучший язык программирования в мире.