Функция os.fork, используемая в примерах из предыдущего раздела, недоступна в стандартной версии Python для Windows, но функция os.pipe доступна. Так как все потоки выполнения работают в рамках одного процесса и совместно используют дескрипторы файлов (и всю глобальную память), это позволяет использовать анонимные каналы для синхронизации потоков выполнения. Это, возможно, более низкоуровневый механизм, чем очереди или общие объекты, и тем не менее он обеспечивает дополнительное средство организации взаимодействий между потоками выполнения. Так, в примере 5.21 демонстрируется тот же способ обмена данными с помощью канала, но уже между потоками, а не между процессами.
Пример 5.21. PP4E\System\Processes\pipe-thread.py
# анонимные каналы и потоки выполнения вместо процессов;
# эта версия работает и в Windows
import os, time, threading
def child(pipeout): zzz = 0 while True: time.sleep(zzz) # заставить родителя подождать
msg = (‘Spam %03d’ % zzz).encode() # каналы — двоичные файлы os.write(pipeout, msg) # отправить данные родителю
zzz = (zzz+1) % 5 # переход к 0 после 4
def parent(pipein): while True: line = os.read(pipein, 32) # остановиться до получения данных
print(‘Parent %d got [%s] at %s’ % (os.getpid(), line, time.time()))
pipein, pipeout = os.pipe()
threading.Thread(target=child, args=(pipeout,)).start() parent(pipein)
Так как стандартная версия Python для Windows поддерживает потоки выполнения, данный сценарий будет работать и в Windows. Вывод сценария похож на предыдущий, но взаимодействующими сторонами здесь являются потоки выполнения, а не процессы (обратите внимание, что из-за бесконечных циклов по крайней мере один из потоков выполнения может не завершиться после нажатия комбинации Ctrl—C — чтобы остановить процесс python.exe, выполняющий этот сценарий, в Windows может потребоваться вызвать Диспетчер задач (Task Manager) или закрыть окно консоли):
C:\… |
\PP4E\System\Processes> |
pipe-thread.py |
Parent |
8876 got [b’Spam 000’] |
at 1268579215.71 |
Parent |
8876 got [b’Spam 001’] |
at 1268579216.73 |
Parent |
8876 got [b’Spam 002’] |
at 1268579218.74 |
Parent |
8876 got [b’Spam 003’] |
at 1268579221.75 |
Parent |
8876 got [b’Spam 004’] |
at 1268579225.76 |
Parent |
8876 got [b’Spam 000’] |
at 1268579225.76 |
Parent |
8876 got [b’Spam 001’] |
at 1268579226.77 |
Parent |
8876 got [b’Spam 002’] |
at 1268579228.79 |
…и так далее: Ctrl—C или Диспетчер задач для выхода…
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011