Python Write terminal output to file then read file - python

I'm having trouble writing the terminal output (all print statements) to a textfile then reading that textfile in the same script. I keep getting an I/O error if I close the program to finish writing to the file and then re-open the file to read it, or no output for the final print(file_contents) statement.
Here's my code:
import sys
filename = open("/Users/xxx/documents/python/dump.txt", 'r+')
filename.truncate()
sys.stdout = filename
print('Hello')
print('Testing')
filename.close()
with open("/Users/xxx/documents/python/dump.txt") as file:
data = file.read()
print(file)
Any suggestions would be great! I'm planning to use this to print output's from some longer scripts to a slack channel.
Thanks!

The error you get is:
IOError: [Errno 2] No such file or directory: '/Users/xxx/documents/python/dump.txt' because:
file open mode r+ does not create a file. Use mode w like this:
You have to reattach stdout to console again to print in console.
import sys
filename = open('/Users/xxx/documents/python/dump.txt', 'w')
# filename.truncate() # mode 'w' truncates file
sys.stdout = filename
print('Hello')
print('Testing')
filename.close()
# reattach stdout to console
sys.stdout = sys.__stdout__
with open('/Users/xxx/documents/python/dump.txt') as file:
data = file.read()
print(data)
will print:
Hello
Testing

The problem is you redirect sys.stdout to filename, and then you close the file. Afterwards you can't print anything anymore, since the file is closed.
sys.stdout = filename
..
..
filename.close()
with open("/Users/xxx/documents/python/dump.txt") as file:
data = file.read()
print(file)
The last print statement tries to print output to sys.stdout, which is a closed file.
If you want to get the old behavior back, you need to keep a reference to sys.stdout. This will solve it:
sys_out = sys.stdout
sys.stdout = filename
..
..
filename.close()
sys.stdout = sys_out
with open("/Users/xxx/documents/python/dump.txt") as file:
data = file.read()
print(file)

import sys
filename = open("/Users/xxx/documents/python/dump.txt", 'w')
sys_out = sys.stdout
sys.stdout = filename
print('Hello')
print('Testing')
print('Test')
filename.close()
sys.stdout = sys_out
with open("/Users/xxx/documents/python/dump.txt", 'r') as file:
data = file.read()
print(data)

Related

I am trying to write a new file and return the file size and the output should be 31 in this example but i am getting 0 .(using python)

import os
def create_python_script(filename):
comments = "# Start of a new Python program"
with open(filename, "w") as file:
file.write(comments)
filesize = os.path.getsize(filename)
return(filesize)
print(create_python_script("program.py")
You are reading the file size too soon. Move it outside the with
The below outputs
0
31
Code
import os
def create_python_script(filename):
comments = "# Start of a new Python program"
with open(filename, "w") as file:
file.write(comments)
filesize = os.path.getsize(filename)
return(filesize)
def create_python_script2(filename):
comments = "# Start of a new Python program"
with open(filename, "w") as file:
file.write(comments)
filesize = os.path.getsize(filename)
return(filesize)
print(create_python_script("program.py"))
print(create_python_script2("program.py"))
The contents of the file aren't "flushed" out to the file until the file is closed. Since you are using a context mananger with , the file is closed when you leave the context manager.
You have to close the file before getting the size so the changes will be reflected into the disk. The code will be:
import os
def create_python_script(filename):
comments = "# Start of a new Python program"
with open(filename, "w") as file:
file.write(comments)
filesize = os.path.getsize(filename)
return(filesize)
print(create_python_script("program.py"))
System get file size when file closed not during opening state.
you could try to get filesize at outscope of with clause:
import os
def create_python_script(filename):
comments = "# Start of a new Python program"
with open(filename, "w") as file:
file.write(comments)
filesize = os.path.getsize(filename)
return(filesize)
print(create_python_script("program.py"))
it prints 31 :)
All above answers mentioning context manager scope is correct for sure.
But sometimes, you actually need to know/estimate file size while writing – i.e., when chunking writes or rotating logs.
In this case, you can use file.tell(), which gives you stream position in bytes.

How to toggle sys.stdout between a file and terminal?

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')

Read txt files, results in empty lines

I have some problem to open and read a txt-file in Python. The txt file contains text (cat text.txt works fine in Terminal). But in Python I only get 5 empty lines.
print open('text.txt').read()
Do you know why?
I solved it. Was a utf-16 file.
print open('text.txt').read().decode('utf-16-le')
if this prints the lines in your file then perhaps the file your program is selecting is empty? I don't know, but try this:
import tkinter as tk
from tkinter import filedialog
import os
def fileopen():
GUI=tk.Tk()
filepath=filedialog.askopenfilename(parent=GUI,title='Select file to print lines.')
(GUI).destroy()
return (filepath)
filepath = fileopen()
filepath = os.path.normpath(filepath)
with open (filepath, 'r') as fh:
print (fh.read())
or alternatively, using this method of printing lines:
fh = open(filepath, 'r')
for line in fh:
line=line.rstrip('\n')
print (line)
fh.close()
or if you want the lines loaded into a list of strings:
lines = []
fh = open(filepath, 'r')
for line in fh:
line=line.rstrip('\n')
lines.append(line)
fh.close()
for line in lines:
print (line)
When you open file I think you have to specify how do you want to open it. In your example you should open it for reading like:
print open('text.txt',"r").read()
Hope this does the trick.

Directing print output to a .txt file

Is there a way to save all of the print output to a txt file in python? Lets say I have the these two lines in my code and I want to save the print output to a file named output.txt.
print ("Hello stackoverflow!")
print ("I have a question.")
I want the output.txt file to to contain
Hello stackoverflow!
I have a question.
Give print a file keyword argument, where the value of the argument is a file stream. The best practice is to open the file with the open function using a with block, which will ensure that the file gets closed for you at the end of the block:
with open("output.txt", "a") as f:
print("Hello stackoverflow!", file=f)
print("I have a question.", file=f)
From the Python documentation about print:
The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used.
And the documentation for open:
Open file and return a corresponding file object. If the file cannot be opened, an OSError is raised.
The "a" as the second argument of open means "append" - in other words, the existing contents of the file won't be overwritten. If you want the file to be overwritten instead at the beginning of the with block, use "w".
The with block is useful because, otherwise, you'd need to remember to close the file yourself like this:
f = open("output.txt", "a")
print("Hello stackoverflow!", file=f)
print("I have a question.", file=f)
f.close()
You can redirect stdout into a file "output.txt":
import sys
sys.stdout = open('output.txt','wt')
print ("Hello stackoverflow!")
print ("I have a question.")
Another method without having to update your Python code at all, would be to redirect via the console.
Basically, have your Python script print() as usual, then call the script from the command line and use command line redirection. Like this:
$ python ./myscript.py > output.txt
Your output.txt file will now contain all output from your Python script.
Edit:
To address the comment; for Windows, change the forward-slash to a backslash.
(i.e. .\myscript.py)
Use the logging module
def init_logging():
rootLogger = logging.getLogger('my_logger')
LOG_DIR = os.getcwd() + '/' + 'logs'
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
fileHandler = logging.FileHandler("{0}/{1}.log".format(LOG_DIR, "g2"))
rootLogger.addHandler(fileHandler)
rootLogger.setLevel(logging.DEBUG)
consoleHandler = logging.StreamHandler()
rootLogger.addHandler(consoleHandler)
return rootLogger
Get the logger:
logger = init_logging()
And start logging/output(ing):
logger.debug('Hi! :)')
Another Variation can be... Be sure to close the file afterwards
import sys
file = open('output.txt', 'a')
sys.stdout = file
print("Hello stackoverflow!")
print("I have a question.")
file.close()
Suppose my input file is "input.txt" and output file is "output.txt".
Let's consider the input file has details to read:
5
1 2 3 4 5
Code:
import sys
sys.stdin = open("input", "r")
sys.stdout = open("output", "w")
print("Reading from input File : ")
n = int(input())
print("Value of n is :", n)
arr = list(map(int, input().split()))
print(arr)
So this will read from input file and output will be displayed in output file.
For more details please see https://www.geeksforgeeks.org/inputoutput-external-file-cc-java-python-competitive-programming/
Be sure to import sys module. print whatever you want to write and want to save. In the sys module, we have stdout, which takes the output and stores it. Then close the sys.stdout . This will save the output.
import sys
print("Hello stackoverflow!" \
"I have a question.")
sys.stdout = open("/home/scilab/Desktop/test.txt", "a")
sys.stdout.close()
One can directly append the returned output of a function to a file.
print(output statement, file=open("filename", "a"))

Reading a file in python via read()

Consider this snippet
from sys import argv
script, input_file = argv
def print_all(f):
print f.read()
current_file = open(input_file)
print_all(current_file)
Ref. line 4: Why do I have to use "print" along with "f.read()". When I use just f.read() it doesnt print anything, why ?
f.read() reads the file from disk into memory. print prints to the console. You will find more info on input and output in the documentation

Categories

Resources