Ok installed python on a Windows machine so I could replicate this 1:1.
Getting acclimated here it looks like without error stream redirection the python script is only outputting one object to the pipeline, a string. WITH redirection there’s two objects getting sent through the pipeline, one string and one error record.
I think then the confusion might be coming from how Tee-Object in Powershell might differ.
Tee-Object
By default Tee-Object sends the input
object to two places; the filepath AND the pipeline. If there is no additional pipe statement then that second output would be standardout, or the console right?
Replicating your initial post:
I get two objects input to Tee-Object (the string “This is standard output” and the Error record), it correctly sends both objects to the filepath AND to the pipeline (output here).
The contents of out.txt look like this:
This is standard output
.\python.exe : This is error
At line:1 char:1
+ .\python.exe C:\temp\test_script.py 2>&1| Tee-Object -FilePath c:\tem ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (This is error:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
So i’ve got a 1:1 copy of what was output to the console. I think then that this is working by design and is more of an issue of mixing languages together.
If you simply want to record an error message like “This is an error” you don’t need an actual ErrorRecord object for that you can just pass the text out right?
If you want to deal with the objects themselves you can do something kind of hacky like this:
.\python.exe C:\temp\test_script.py 2>&1| %{if($_.Gettype().name -eq "ErrorRecord"){$_.Exception}else{$_}} | Tee-Object -FilePath c:\temp\out.txt
and out.txt contains:
This is standard output
This is error
What we did there was redirect the error stream from the first execution to standard out, pipe that to % (Foreach-Object) and do a simple comparison:
if ($_.GetType().Name -eq "ErrorRecord") {
$_.Exception
}
We look at the time of the object with the built-in GetType method, then pull the Name property from there. If it’s an ErrorRecord its name will match. If that logic proves true then on that object we call the Exception property which will be your original text from Python.
Else, we just pass the object on. So basically we shimmed another pipeline inbetween your python and your Tee-Object.