Как заставить команды python работать вместе перед переключением контекста? - PullRequest
0 голосов
/ 15 октября 2019

У меня запущено 2 процесса, и каждый печатает файл конфигурации, которым он владеет. Конфигурационный файл не содержит уникальных данных, которые я могу отследить, поэтому у меня нет возможности узнать, какой процесс напечатал что.

Способ обработки, который добавлял префикс печати:

def print_config(proc_name):
    print(proc_name)
    print_conf()

# both processes are given the target print_config,
# args='a' or 'b', and then are started

Тем не менее, ОС упорядочивает команды в следующем порядке:

1. Proc A: print(proc_name)
2. Proc B: print(proc_name)
3. Proc ?: print_conf()
4. Proc ??: print_conf()

Как я могу объединить распечатки, чтобы я увидел печать (proc_name) и сразу после print_conf?

1 Ответ

1 голос
/ 15 октября 2019

Вы можете использовать объекты блокировки для контроля исполнения ваших потоков. По сути, принцип состоит в том, чтобы заблокировать глобальный объект перед печатью и отпустить его после завершения печати, чтобы другой поток мог получить к нему доступ, последовательно заблокировать его и выполнить саму печать. Вот один из примеров (взят из bogotobogo.com ):

import threading
import time
import logging
import random

logging.basicConfig(level=logging.DEBUG,
                    format='(%(threadName)-9s) %(message)s',)

class Counter(object):
    def __init__(self, start = 0):
        self.lock = threading.Lock()
        self.value = start
    def increment(self):
        logging.debug('Waiting for a lock')
        self.lock.acquire()
        try:
            logging.debug('Acquired a lock')
            self.value = self.value + 1
        finally:
            logging.debug('Released a lock')
            self.lock.release()

def worker(c):
    for i in range(2):
        r = random.random()
        logging.debug('Sleeping %0.02f', r)
        time.sleep(r)
        c.increment()
    logging.debug('Done')

if __name__ == '__main__':
    counter = Counter()
    for i in range(2):
        t = threading.Thread(target=worker, args=(counter,))
        t.start()

    logging.debug('Waiting for worker threads')
    main_thread = threading.currentThread()
    for t in threading.enumerate():
        if t is not main_thread:
            t.join()
    logging.debug('Counter: %d', counter.value)

ОБНОВЛЕНИЕ:

Кроме того, если вы не спрашиваете о блокировке потоков, то на самом делеманипулируя выводом двух независимых скриптов, концепция совершенно та же, за исключением того, что вы можете использовать файл блокировки для этой цели. Допустим, у вас есть два довольно похожих сценария: первый:

import os.path

while(os.path.exists("lock.LCK")):
        continue


f = open("lock.LCK", "w+")
file_for_output = open("output.txt", "a")
file_for_output.write("Hi2\n")
file_for_output.write("There2\n")
f.close()
os.remove("lock.LCK")
file_for_output.close()

и другой:

import os.path

while(os.path.exists("lock.LCK")):
        continue


f = open("lock.LCK", "w+")
file_for_output = open("output.txt", "a")
file_for_output.write("Hi1\n")
file_for_output.write("There1\n")
f.close()
os.remove("lock.LCK")
file_for_output.close()

Если вы запустите эти 2 файла одновременно, 1 придетсядождитесь, пока другой закончит запись, из-за защиты файла блокировки в мертвом цикле while. Обратите внимание, что это только основной пример того, как эта проблема может быть решена. Если вы хотите реализовать это в реальном коде, я действительно советую установить ограничение времени ожидания для мертвого цикла и надлежащие исключения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...