Сценарий Python в crontab получает входные аргументы другого процесса, выполняющегося одновременно - PullRequest
2 голосов
/ 19 сентября 2010

Я запускаю 2 скрипта Python из crontab одновременно каждые 30 минут, например

00,30 6-19 * * 0-5 /.../x.py site1
*/3 6-19 * * 0-5 /.../y.py site2

Вначале оба сценария импортируют модуль, который печатает некоторые данные в журнал, например,

name = os.path.basename(sys.argv[0])
site = sys.argv[1]
pid = os.getpid()

Иногда (!) Второй сценарий y выводит в журнал входные аргументы сценария x: имя = х и сайт = сайт1 напечатанный PID процессов не совпадает. Почему это происходит и как я могу избежать этого?

P.S. Я подозреваю, что проблема связана с регистратором, который я использую. Может ли скрипт использовать логгер, созданный в другом скрипте? В этом случае он будет печатать в каждой строке данные, относящиеся к первому сценарию. Каждый скрипт выполняет один и тот же код:

log = logging.getLogger('MyLog')
    log.setLevel(logging.INFO)
    dh = RotatingSqliteHandler(os.path.join(progDirs['log'],'sqlitelog'),processMeta, 5000000)
    log.addHandler(dh)

Обработчик логгера определяется следующим образом:

class RotatingSqliteHandler(logging.Handler):
   def __init__(self, filename, progData, maxBytes=0):
       logging.Handler.__init__(self)
       self.user = progData['user']
       self.host = progData['host']
       self.progName = progData['name']
       self.site = progData['site']
       self.pid = random.getrandbits(50)
    .....

в журнале я вижу, что идентификатор процесса, который генерирует регистратор в последней строке, одинаков для обоих сценариев.

Я попытаюсь использовать имя регистратора, уникальное для каждого запуска скрипта, вместо «MyLog». Хотя странно, что экземпляр регистратора можно получить из другого процесса.

Ответы [ 4 ]

2 голосов
/ 26 сентября 2010

Невозможно, чтобы один процесс Python получил доступ к объекту из другого процесса Python, если для этого не предусмотрено отдельное условие, например, с помощью. модуль multiprocessing. Поэтому я не верю, что это происходит, независимо от того, как это выглядит на поверхности.

Чтобы подтвердить это, используйте альтернативный обработчик (например, FileHandler или RotatingFileHandler), чтобы проверить, сохраняется ли проблема. Если это не так, то вам следует изучить логику RotatingSqliteHandler.

Если это произойдет, и если вы сможете придумать небольшой автономный скрипт, который неоднократно демонстрирует проблему, пожалуйста, опубликуйте проблему на bugs.python.org, и я обязательно посмотрю. (Я поддерживаю пакет журналов Python.)

2 голосов
/ 19 сентября 2010

Когда два сценария «запускаются одновременно», строки, которые они печатают, могут смешиваться в зависимости от того, как операционная система назначает приоритет процессам.

Таким образом, вы можете получить в своих журналах:что-то вроде:

x.py: /tmp/x.py
…
… # Other processes logging information
…
y.py: /tmp/y.py
x.py: site1  # Not printed by y!!
x.py: PID = 123
…
… # Other processes logging information
…
y.py: site2
y.py: PID = 124

Вы все еще наблюдаете проблему, если вы префикс каждой строки с базовым именем каждой программы?

0 голосов
/ 21 сентября 2010

Этот вопрос меня озадачивает: вот еще одна идея! Генератор случайных чисел может быть засеян с «текущим системным временем» (если на компьютере не существует источника случайных чисел). В Python 2.7 это делается с помощью вызова time.time(). Дело в том, , что «не все системы обеспечивают время с точностью, превышающей 1 секунду». В более общем случае, возможно, что иногда ваши x.py и y.py работают достаточно близко друг к другу, что time.time() одинаково для обоих процессов , так что random.getrandbits(50) дает одинаковое для обоих из них? Это было бы совместимо с проблемой, возникающей только в исключительных случаях, как вы заметили.

Каково "разрешение" time.time() на вашем компьютере (наименьший интервал между различными временами)? возможно, он достаточно велик для того, чтобы два случайных генератора были исключены одинаково.

0 голосов
/ 20 сентября 2010

Может ли это быть каким-либо образом связано со следующей точкой ?

getLogger () возвращает ссылку на экземпляр регистратора с указанным именем, если оно предоставлено, илирут если нет.Имена представляют собой иерархические структуры, разделенные точками. Несколько вызовов getLogger () с одним и тем же именем вернут ссылку на один и тот же объект регистратора.

Может ли оба ваших скрипта быть достаточно "связаны" друг с другом,играет роль?Например, если y.py import x.py, то вы получаете один и тот же регистратор в x.py и y.py, когда вы вызываете logging.getLogger('myLog') в каждом из них.

...