7

I'm running multiple Python scripts in PowerShell, and I want at specific condition in Python script to notify PowerShell main script. Like throwing an error from Python and catching it with PowerShell.

Python example:

import os
print "Running Python script ..."
raise Exception("This Error is coming from Python")

And PowerShell main script:

$ErrorActionPreference = 'Stop'
try {
    python runThisScript.py -ErrorAction Stop
    # Write-Error -Message 'Oh no! An error!'
    Write-Host "What is that?"
} catch {
    Write-Host $_.Exception.Message -ForegroundColor Green
    throw [System.Exception] "Python scrip XXX failed"
} finally {
    Write-Host "This is the final block ..."
}

But this does not work. It will show:

Running Python script ...
Traceback (most recent call last):
  File "runThisScript.py", line 5, in <module>
    raise Exception("This Error is coming from Python")
Exception: This Error is coming from Python
What is that?
This is the final block ...

If I un-comment the line Write-Error -Message 'Oh no! An error!' this is what I want to see (the error is catch and handle by PowerShell).

Oh no! An error!
This is the final block ...
Python scrip XXX failed
At C:\Automation\general_stuff\tc\mainTestRunner.ps1:12 char:5
+     throw [System.Exception] "Python scrip XXX failed"
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], Exception
    + FullyQualifiedErrorId : Python scrip XXX failed

Thank you in advance for your comments.

9
  • 3
    You can utilize return codes and capture outputs. $out = python script.py; if ($LASTEXITCODE -ne 0) { $out } Commented Jul 2, 2018 at 18:37
  • 1
    This is pretty close to on point: stackoverflow.com/questions/11004666/…. See the highest upvoted answer. @TheIncorrigible1's comment is the TL;DR version of the answer as well. Commented Jul 2, 2018 at 18:43
  • Indeed, this it works. Thank you @TheIncorrigible1 and Matthew! Commented Jul 3, 2018 at 7:22
  • @TheIncorrigible1 - want to post an answer for him to accept, or dupe to another question? Commented Jul 3, 2018 at 19:05
  • 1
    I don't agree with Duplicate in this case. My question was about a way to communicate between Python and PowerShell. $LASTEXITCODE is an workaround, not a direct way. Also, there are more ways to do the same thing: in Python, log the notification in a text file then when is finish, read the notification from log file directly in PowerShlell ... same result, different approach. Commented Jul 4, 2018 at 9:58

1 Answer 1

1

If you want to get the details of the error, and it is okay to get the output printed all at once only after the script has completed, you can consider producing the Exception details (or whichever error message you want) to stderr, and running the script as a subprocess in PowerShell.

In Python you would print to sys.stderr and exit with any error code which is not 0, so that you clearly communicate to the PowerShell script that something went wrong.

from sys import stderr, exit
try:
    raise Exception("This is a test exception")
except Exception as e:
    print(f"{e.__class__.__name__}: {e}", file=stderr, flush=True)
    exit(1)

Then, in PowerShell, you would invoke the script as a process, so that you can capture stdout and stderr:

$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName  = "python"
$psi.Arguments = "yourscript.py"
$psi.RedirectStandardOutput = $true
$psi.RedirectStandardError  = $true
$psi.UseShellExecute = $false

$p = [System.Diagnostics.Process]::Start($psi)
$p.WaitForExit()

Then you can pull the outputs and work with them according to your preferences:

$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()

if ($p.ExitCode -eq 0) {
    Write-Host $stdout
} else {
    Write-Error -Message $stderr -Category OperationStopped
    # or just Write-Host $stderr
}

The -Category can be any of these:

NotSpecified, OpenError, CloseError, DeviceError, DeadlockDetected, InvalidArgument, InvalidData, InvalidOperation, InvalidResult, InvalidType, MetadataError, NotImplemented, NotInstalled, ObjectNotFound, OperationStopped, OperationTimeout, SyntaxError, ParserError, PermissionDenied, ResourceBusy, ResourceExists, ResourceUnavailable, ReadError, WriteError, FromStdErr, SecurityError, ProtocolError, ConnectionError, AuthenticationError, LimitsExceeded, QuotaExceeded, NotEnabled

I recall there is a way to pull the stdout while the process is still running, unfortunately I haven't explored it yet.

You can do this in general for other processes that return a proper non-zero error code and that have a specialised output to stderr.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.