@kudrbudr

Как закрыты зависшие терминалы Python в Windows 11 Pro?

Привет, запускаю Python скрипты с наивысшими правами, с принудительным завершением задачи через 45 минут (Windows 11 планировщик). (спойлер: планировщик не помогает)

После завершения работы скрипта SeleniumBase пытаюсь закрыть терминал Python через sys.exit(0), планировщик Windows показывает успешное выполнение задачи.

Но терминал остается не закрытым несмотря на sys.exit(0), не смог победить эту проблему перписав свой скрипт, поэтому решил поступить иначе: сделал скрипт который находит процессы Chrome и убивает их:

function Invoke-TasksWithGlobalTimeout {
    param (
        [int]$timeoutMinutes = 1
    )

    $timeoutSeconds = $timeoutMinutes * 60
    $interval = 10 # интервал проверки состояния задачи в секундах

    # Список задач
    $tasks = @("Задача 1")

    # Запускаем все задачи в фоновом режиме
    foreach ($task in $tasks) {
        Start-Job -ScriptBlock {
            param($task)
            Write-Host "Проверка задачи: $task"
            $status = (Get-ScheduledTask -TaskName $task).State
            while ($status -eq "Running" -or $status -eq "Queued") {
                Write-Host "Задача $task выполняется или находится в очереди. Ждем..."
                Start-Sleep -Seconds 10
                $status = (Get-ScheduledTask -TaskName $task).State
            }
            Write-Host "Отключение задачи: $task"
            Disable-ScheduledTask -TaskName $task
        } -ArgumentList $task
    }

    # Устанавливаем таймер на 1 час
    $timer = [System.Diagnostics.Stopwatch]::StartNew()

    # Таймер обратного отсчета
    for ($i = $timeoutSeconds; $i -gt 0; $i--) {
        Write-Host "Осталось времени: $i секунд..." -NoNewline
        Start-Sleep -Seconds 1
        Write-Host "`r" -NoNewline
    }
    Write-Host "`n"

    # Принудительное завершение всех задач после таймера
    Write-Host "Таймер истек. Принудительное завершение всех задач..."
    foreach ($task in $tasks) {
        $taskInfo = Get-ScheduledTask -TaskName $task
        if ($taskInfo.State -eq "Running") {
            Write-Host "Завершение задачи: $task"
            Stop-ScheduledTask -TaskName $task
        }
    }

    Write-Host "Статус задач не является 'Выполняется' или 'В очереди', выполняем ваш код."

    # Ваш код, который нужно выполнить после завершения процесса Python
    $chromePids = (Get-Process chrome -ErrorAction SilentlyContinue).Id

    Write-Output "Количество процессов Chrome для закрытия: $($chromePids.Count)"

    if ($chromePids) {
        Write-Host "Закрытие процессов Chrome..."
        $chromePids | ForEach-Object { taskkill /f /pid $_ }
    }

    # Включаем задачи снова
    foreach ($task in $tasks) {
        Write-Host "Включение задачи: $task"
        Enable-ScheduledTask -TaskName $task
    }
}

# Запускаем задачи с глобальным таймаутом
Invoke-TasksWithGlobalTimeout -timeoutMinutes 1


Вопрос: Можно каким-то образом завершить Python скрипт со всеми дочерними процессами как Chrome, терминал Python прописав какой-то код в питон скрипт аналогичный sys.exit(0)?

Терминал зависает видимо из-за внешних факторов: мб какие-то файлы скачанные заблокированы из-за "наивысшего доступа" , или OneDrive пытается синхронизировать новые скачанные файлы (скрипт находит в директории OneDrive).

Перенос на другой диск не дал результатов, обычный запуск на VS Code или даже через терминал без прав админа завершается нормально, и терминал закрывается.

Еще написал вто такой скрипт который тоже убивает терминалы, но не так эффективно как первый вариант:

# Определяем путь к исполняемому файлу Python
$pythonPath = "C:\Program Files\Python312\python.exe"

# Бесконечный цикл
while ($true) {
    # Получаем список процессов Python
    $pythonProcesses = Get-Process | Where-Object { $_.Path -eq $pythonPath }

    foreach ($process in $pythonProcesses) {
        # Получаем время создания процесса
        $creationTime = $process.StartTime
        
        # Текущее время
        $currentTime = Get-Date
        
        # Вычисляем разницу во времени
        $timeDifference = $currentTime - $creationTime
        
        # Вычисляем количество минут с момента запуска процесса
        $minutesAgo = [math]::Round($timeDifference.TotalMinutes)

        # Если процесс работает больше часа
        if ($timeDifference.TotalMinutes -gt 90) {
            # Закрываем процесс
            Stop-Process -Id $process.Id -Force
            
            # Логируем закрытие процесса красным цветом
            Write-Host "Закрыт процесс $($process.Id) запущенный $minutesAgo минут назад ($creationTime)" -ForegroundColor Red
        } else {
            # Логируем активные процессы зеленым цветом
            Write-Host "Процесс $($process.Id) запущен $minutesAgo минут назад ($creationTime)" -ForegroundColor Green
        }
    }
    
    # Таймер отсчета
    for ($i = 60; $i -gt 0; $i--) {
        Write-Host "Следующая проверка через $i секунд..." -NoNewline
        Start-Sleep -Seconds 1
        Write-Host "`r" -NoNewline
    }
    Write-Host "`n"
}
  • Вопрос задан
  • 736 просмотров
Пригласить эксперта
Ответы на вопрос 1
@eminsk
программирую на python
import os
import signal
os.kill(os.getpid(), signal.SIGTERM)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы