I want to do something like this in the python interpreter.
myhelp = help(myclass)
but the output goes to stdout. Is it possible to assign it to a variable?
Thanks!
You can capture stdout while help(myclass) runs:
from cStringIO import StringIO
import sys
stdout = sys.stdout
buffer = StringIO()
sys.stdout = buffer
help(myclass)
sys.stdout = stdout
myhelp = buffer.getvalue()
Related
I know that if you want to redirect stdout to a file, you can simply do it like this.
sys.stdout = open(fpath, 'w')
But how can I switch back stdout to write on the terminal?
You can assign it to variable and later assing it back
temp = sys.stdout
print('console')
sys.stdout = open('output.txt', 'w')
print('file')
sys.stdout = temp
print('console')
You can also find examples how to use it with context manager so you can change it using with
import sys
from contextlib import contextmanager
#contextmanager
def custom_redirection(fileobj):
old = sys.stdout
sys.stdout = fileobj
try:
yield fileobj
finally:
sys.stdout = old
# ---
print('console')
with open('output.txt', 'w') as out:
with custom_redirection(out):
print('file')
print('console')
Code from: Python 101: Redirecting stdout
Currently you can even find redirect_stdout in contextlib
import sys
from contextlib import redirect_stdout
print('console')
with open('output.txt', 'w') as out:
with redirect_stdout(out):
print('file')
print('console')
BTW: if you want to redirect all text to file then you can use system/shell for this
$ python script.py > output.txt
A better bet is to simply write to the file when you want.
with open('samplefile.txt', 'w') as sample:
print('write to sample file', file=sample)
print('write to console')
reassigning the stdout would mean you need to track the previous file descriptor and assign it back whenever you want to send text to the console.
If you really must reassign you could do it like this.
holder = sys.stdout
sys.stdout = open(fpath, 'w')
print('write something to file')
sys.stdout = holder
print('write something to console')
I want to get the current console output of my program in python. There are a lot of solutions to get the console output when running an external program, however, I couldn't find any solution for getting the console output of the current program. Am I missing something? I am looking for a solution which works under windows and linux.
For example:
print "Hello world"
output = get_console_output() # Returns "Hello World\n"
Edit:
The solution should preserve the console output, so just replacing stdout won't work, as the console will be empty then
If you want to access the output you need to redirect the standard output stdout somewhere. You can use StringIO for this for example:
from cStringIO import StringIO
import sys
sys.stdout = buffer = StringIO()
print "Hello World"
# get output via: buffer.getvalue()
If you rather want the output to a file you could instead redirect directly to a file:
import sys
sys.stdout = open('output.txt', 'w')
print 'Hello World'
Edit: If you want output to be appended to log (according to comment), I suggest a custom class:
import sys
class Log(object):
def __init__(self):
self.orgstdout = sys.stdout
self.log = open("log.txt", "a")
def write(self, msg):
self.orgstdout.write(msg)
self.log.write(msg)
sys.stdout = Log()
print('Hello World')
You can overwrite sys.stdout with any file-like object:
import sys
import StringIO
sys.stdout = StringIO.StringIO()
You should also think about using the logging module instead of print. Or simply write a function that stores and prints values.
I'm looking for a better way to do this, if possible:
import subprocess
f = open('temp.file', 'w+')
f.write('hello world')
f.close()
out = subprocess.check_output(['cat', 'temp.file'])
print out
subprocess.check_output(['rm', 'temp.file'])
In this example I'm creating a file and passing it as input to cat (in reality it's not cat I'm running but some other program that parses an input pcap file).
What I'm wondering is, is there a way in Python I can create a 'file-like object' with some content, and pipe this file-like object as input to a command-line program. If it is possible, I reckon it would be more efficient than writing a file to the disk and then deleting that file.
check_output takes a stdin input argument to specify a file-like object to connect to the process's standard input.
with open('temp.file') as input:
out = subprocess.check_output(['cat'], stdin=input)
Also, there's no need to shell out to run rm; you can remove the file directly from Python:
os.remove('temp.file')
You can write to a TemporaryFile
import subprocess
from tempfile import TemporaryFile
f = TemporaryFile("w")
f.write("foo")
f.seek(0)
out = subprocess.check_output(['cat'],stdin=f)
print(out)
b'foo'
If you just want to write to a file like object and get the content:
from io import StringIO
f = StringIO()
f.write("foo")
print(f.getvalue())
If the program is configured to read from stdin, you can use Popen.communicate:
>>> from subprocess import Popen, PIPE
>>> p = Popen('cat', stdout=PIPE, stdin=PIPE, stderr=PIPE)
>>> out, err = p.communicate(input=b"Hello world!")
>>> out
'Hello world!'
If the command accepts only filenames, if it doesn't read input from its stdin i.e., if you can't use stdin=PIPE + .communicate() or stdin=real_file then you could try /dev/fd/# filenames:
#!/usr/bin/env python3
import os
import subprocess
import threading
def pump_input(pipe):
with pipe:
for i in range(3):
print(i, file=pipe)
r, w = os.pipe()
try:
threading.Thread(target=pump_input, args=[open(w, 'w')]).start()
out = subprocess.check_output(['cat', '/dev/fd/'+str(r)], pass_fds=[r])
finally:
os.close(r)
print('got:', out)
No content touches the disk. The input is passed to the subprocess via the pipe directly.
If you have a file-like object that is not a real file (otherwise, just pass its name as the command-line argument) then pump_input() could look like:
import shutil
def pump_input(pipe):
with pipe:
shutil.copyfileobj(file_like_object, pipe)
I make a custom command in Django where make some output to stdout.
How I can intercept stdout make some changes(for example add prefix) and write to stderr?
This is test task so do not pay attention on illogicality of question.
You can use StringIO like this:
from io import StringIO
import sys
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
print("test")
sys.stdout = old_stdout
s = mystdout.getvalue()
s = "prefix" + s
sys.stderr.write(s)
The code is capturing stdout into the buffer, then reads the buffer, adds prefix and writes to stderr.
Also see:
Can I redirect the stdout in python into some sort of string buffer?
You can use sys.stdout and sys.stderr:
from sys import stdout, stderr
output_text = "Some text"
stdout.write('stdout: ' + output_text + '\n')
stderr.write('stderr: ' + output_text + '\n')
Demo:
monty#xonix:~/py$ python so.py &> foo.txt
monty#xonix:~/py$ cat foo.txt
stderr: Some text
stdout: Some text
I'm trying to write a python script that will allow me to take the output from a command and to put that into a file or variable (Preferability a variable).
In my code, I have redirected the output to a StringIO() object. From that, I want take the output a command and to put it into that StringIO() object.
Here is a sample of my code:
from StringIO import StringIO
import sys
old_stdout = sys.stdout
result = StringIO()
sys.stdout = result
# This will output to the screen, and not to the variable
# I want this to output to the 'result' variable
os.system('ls -l')
Also, how do I take result and put it into a string?
Thanks in advance!!
import subprocess
sp = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
output, _ = sp.communicate()
print "Status:", sp.wait()
print "Output:"
print output