Ошибка нехватки памяти в Python win32com

Чтобы управлять сторонним устройством, я использую модуль win32com python для взаимодействия с предоставленным пользовательским интерфейсом. В целом это работает так, как ожидалось, но редко (каждые 10 тыс. Вызовов или около того) COM API выдает ошибку -2147024888 (0x80070008) с описанием not enough storage is available to process this command. Это очень раздражает, потому что обычно ночью происходит выход из строя устройства, и процедуру запуска необходимо полностью повторять.

Теперь вопрос в том, что на самом деле не хватает памяти, потому что я совершенно определенно не сталкиваюсь с какими-либо ограничениями по ОЗУ. Углубившись в проблему, я обнаружил, что я также не могу закрыть и снова открыть COM-соединение, поскольку это приводит к ошибке -2147024882 (0x8007000e), описанной как out of memory. Однако this намекает, что на самом деле здесь нет проблем с памятью. Еще одно объяснение: здесь предлагается слишком много используемых дескрипторов.

Эта идея будет подкреплена наблюдением, что я больше не могу разветвлять потоки на данный момент. Позвонив start() на threading.Thread, я получаю

RuntimeError: can't start new thread

хотя согласно threading.active_count() выполняется только 4 потока. В то же время ни одна из этих проблем не наблюдается в другом процессе, на котором запущен python. Следовательно, я подозреваю, что в моем процессе не хватает ресурсов, но я не знаю, какие именно. На данный момент я вижу два варианта дальнейших действий.

  • Вариант 1. Узнайте, из каких ресурсов заканчивается мой процесс. Однако я не особо разбираюсь в отладке. Что я мог сделать, чтобы лучше понять, что происходит за кулисами?

  • Вариант 2: живите с проблемой и работайте над ее решением. В этом случае ловушки ошибок оказывается недостаточно. Как только возникает ошибка, кажется, нет никакого способа заставить все снова работать, не убивая процесс python. Конечно, это невозможно изнутри Python.

    В качестве решения я подумал об использовании модуля multiprocessing и наличия всех связанных с устройством вызовы выполняются в отдельном процессе. Если что-то пойдет не так, я завершаю процесс в своей основной программе и запускаю ее снова с возможностью продолжить с того места, где произошла ошибка.

Для обоих вариантов я был бы рад предложениям или рекомендациям. Может быть, есть еще что-то совсем другое, о чем я не думал. Любая помощь приветствуется.


Изменить: мотивированный комментарием Бена, я просмотрел некоторые свойства все еще выполняющегося процесса, в котором произошли ошибки. Вот список данных, которые я считаю потенциально полезными:

  • 1,7 Гбайт при использовании только 21 Мбайт и пиковой памяти 500 Мбайт (на Win7 x86)
  • 800k ошибок подкачки
  • 772 ручки
  • 20 потоков

person ranguwud    schedule 11.03.2016    source источник
comment
Используйте вкладку «Сведения или процессы» диспетчера задач и включите дополнительные столбцы. Один из них - счетчик дескрипторов, другой - счетчик потоков, также см. Плату за фиксацию, которая представляет собой выделение памяти для процесса. Вы скоро увидите, что у вас заканчивается. Монитор производительности также поможет.   -  person Ben    schedule 11.03.2016
comment
Спасибо за предложение. Я внес изменения, чтобы включить данные, которые считаю потенциально актуальными.   -  person ranguwud    schedule 11.03.2016
comment
А как насчет всех остальных процессов? У кого-то есть большое количество дескрипторов или потоков или размер фиксации?   -  person Ben    schedule 11.03.2016
comment
К сожалению, я не знаю, что здесь означает высокий. Каждый другой процесс имеет не более 2000 дескрипторов или 100 потоков. Размер фиксации 1,7 Гб рассматриваемого процесса на сегодняшний день является самым высоким. Следующий меньший thrad имеет размер фиксации только 200M. Единственный интерес, который я могу прочитать, это то, что процесс со 100 потоками принадлежит среде IDE python (Spyder), из которой запускается моя программа.   -  person ranguwud    schedule 11.03.2016
comment
Как эти числа меняются при запуске программы? Они постепенно увеличиваются до краха? Или они просто остаются на этом номере?   -  person Ben    schedule 11.03.2016
comment
Пока не знаю. Поскольку сбой происходит только каждые 10 тысяч вызовов или около того, я никогда не наблюдал его в реальном времени, а видел только последствия, когда вся программа зависала. Также для меня нет очевидного способа воспроизвести сбой. Любые идеи?   -  person ranguwud    schedule 11.03.2016
comment
Просто смотрите на цифры, пока запускаете программу! Они идут вверх?   -  person Ben    schedule 11.03.2016
comment
После тестов я не могу нарисовать внятную картину. Сегодня вечером я действительно наблюдал непрерывное увеличение использования ОЗУ, но сегодня я снова выполняю тот же самый код, но не. Итак, моя интерпретация состоит в том, что сборщик мусора python сегодня вечером был немного ленив. Кроме того, когда я подключаю профилировщик памяти, я не получаю никаких намеков на утечку памяти. Следовательно, с очень большой вероятностью проблема должна быть в другом.   -  person ranguwud    schedule 12.03.2016
comment
Я сталкиваюсь почти с такой же проблемой при использовании os.system или subprocess. Это так странно, что при каждом выполнении примерно 280 popen или os.system команд мой скрипт python выдает эту ошибку. Я пробовал gc.collect() и subprocess._cleanup(), но ни один из них не работал.   -  person tigertang    schedule 14.11.2019
comment
Кроме того, я никогда не видел увеличения использования памяти по мере выполнения сценария, а было всего несколько подпроцессов.   -  person tigertang    schedule 14.11.2019
comment
@tigertang Проблема, описанная в моем вопросе, больше не существует, но я так и не узнал, что заставило ее исчезнуть. Однако я верю, что основной причиной была переменная, инициализированная неправильным типом. Я записал свое мнение об этом здесь. Относится ли это как-то к вашему subprocess, я не могу сказать.   -  person ranguwud    schedule 26.11.2019
comment
@rangud Я обнаружил ошибку через несколько дней после того, как прокомментировал этот вопрос. Это не связано с subprocess. Это связано с тем, что сторонняя библиотека продолжала добавлять системные пути до тех пор, пока не будет достигнута максимальная длина пути. Блин, а как можно сообщить об ошибке не хватает места для хранения? Это так обманчиво!   -  person tigertang    schedule 26.11.2019