How to Redirect Stdout to Both File and Console with Scripting

Redirect stdout to a file in Python?

If you want to do the redirection within the Python script, setting sys.stdout to a file object does the trick:

# for python3
import sys
with open('file', 'w') as sys.stdout:
print('test')

A far more common method is to use shell redirection when executing (same on Windows and Linux):

$ python3 foo.py > file

Python: stdout to both console and textfile including errors

If you are using bash (minimum version 4), you can run: ./mystdout |& tee output.txt. Otherwise your suggestion ./mystdout 2>&1 | tee output.txt should also work.

How to redirect output to a file and stdout

The command you want is named tee:

foo | tee output.file

For example, if you only care about stdout:

ls -a | tee output.file

If you want to include stderr, do:

program [arguments...] 2>&1 | tee outfile

2>&1 redirects channel 2 (stderr/standard error) into channel 1 (stdout/standard output), such that both is written as stdout. It is also directed to the given output file as of the tee command.

Furthermore, if you want to append to the log file, use tee -a as:

program [arguments...] 2>&1 | tee -a outfile

How to output to the console and file?

I came up with this [untested]

import sys

class Tee(object):
def __init__(self, *files):
self.files = files
def write(self, obj):
for f in self.files:
f.write(obj)
f.flush() # If you want the output to be visible immediately
def flush(self) :
for f in self.files:
f.flush()

f = open('out.txt', 'w')
original = sys.stdout
sys.stdout = Tee(sys.stdout, f)
print "test" # This will go to stdout and the file out.txt

#use the original
sys.stdout = original
print "This won't appear on file" # Only on stdout
f.close()

print>>xyz in python will expect a write() function in xyz. You could use your own custom object which has this. Or else, you could also have sys.stdout refer to your object, in which case it will be tee-ed even without >>xyz.

How to redirect and append both standard output and standard error to a file with Bash

cmd >>file.txt 2>&1

Bash executes the redirects from left to right as follows:

  1. >>file.txt: Open file.txt in append mode and redirect stdout there.
  2. 2>&1: Redirect stderr to "where stdout is currently going". In this case, that is a file opened in append mode. In other words, the &1 reuses the file descriptor which stdout currently uses.

Redirecting stdout and stderr to file and console

Taking a cue from this blog post you could write a custom tee function that distinguishes input by object type and writes to the corresponding output file. Something like this:

function Tee-Custom {
[CmdletBinding()]
Param(
[Parameter(
Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true
)]
[array]$InputObject,

[Parameter(Mandatory=$false)]
[string]$OutputLogfile,

[Parameter(Mandatory=$false)]
[string]$ErrorLogfile,

[Parameter(Mandatory=$false)]
[switch]$Append
)

Begin {
if (-not $Append.IsPresent) {
if ($OutputLogfile -and (Test-Path -LiteralPath $OutputLogfile)) {
Clear-Content -LiteralPath $OutputLogfile -Force
}
if ($ErrorLogfile -and (Test-Path -LiteralPath $ErrorLogfile)) {
Clear-Content -LiteralPath $ErrorLogfile -Force
}
}
}
Process {
$InputObject | ForEach-Object {
$params = @{'InputObject' = $_}
if ($_ -is [Management.Automation.ErrorRecord]) {
if ($ErrorLogfile) { $params['FilePath'] = $ErrorLogfile }
} else {
if ($OutputLogfile) { $params['FilePath'] = $OutputLogfile }
}
Tee-Object @params -Append
}
}
}

which could be used like this:

& program.exe 2>&1 | Tee-Custom -OutputLogfile 'out.log' -ErrorLogfile 'err.log' -Append


Related Topics



Leave a reply



Submit