how to direct output into a txt file in python in windows - python

import itertools
variations = itertools.product('abc', repeat=3)
for variations in variations:
variation_string = ""
for letter in variations:
variation_string += letter
print (variation_string)
How can I redirect output into a txt file (on windows platform)?

From the console you would write:
python script.py > out.txt
If you want to do it in Python then you would write:
with open('out.txt', 'w') as f:
f.write(something)
Obviously this is just a trivial example. You'd clearly do more inside the with block.

You may also redirect stdout to your file directly in your script as print writes by default to sys.stdout file handler. Python provides a simple way to to it:
import sys # Need to have acces to sys.stdout
fd = open('foo.txt','w') # open the result file in write mode
old_stdout = sys.stdout # store the default system handler to be able to restore it
sys.stdout = fd # Now your file is used by print as destination
print 'bar' # 'bar' is added to your file
sys.stdout=old_stdout # here we restore the default behavior
print 'foorbar' # this is printed on the console
fd.close() # to not forget to close your file

In window command prompt, this command will store output of program.py into file output.txt
python program.py > output.txt

If it were me, I would use David Heffernan's method above to write your variable to the text file (because other methods require the user to use a command prompt).
import itertools
file = open('out.txt', 'w')
variations = itertools.product('abc', repeat=3)
for variations in variations:
variation_string = ""
for letter in variations:
variation_string += letter
file.write(variation_string)
file.close()

you may use >>
log = open("test.log","w")
print >> log, variation_string
log.close()

Extension to David's answer
If you are using PyCharm,
Go to Run --> Edit Configurations --> Logs --> Check mark Save console
output to file --> Enter complete path --> Apply

Related

Run command in CMD via python and extract the data

I am trying to use the below code to run a command and extract the data from the cmd.
the file with the commands and data is a txt file. (let me know if I should change it or use an excel if better).
the commands look something like this: ping "host name" which would result in some data in the cmd.there is list of these in the file. so it would ping "hostname1" then line two ping "hostname2"..etc
THE QUESTION: I want it to run every line individually and extract the results from the cmd and store them in a txt file or excel file - Ideally I want all the results in the same file. is this possible? and how?
here is the code so far:
root_dir = pathlib.Path(r"path to file here")
cmds_file = root_dir.joinpath('actual file here with commands and data')
#fail = []
cmds = cmds_file.read_text().splitlines()
try:
for cmd in cmds:
args = cmd.split()
print(f"\nRunning: {args[0]}")
output = subprocess.check_output(args)
print(output.decode("utf-8"))
out_file = root_dir.joinpath(f"Name of file where I want results printed in")
out_file.write_text(output.decode("utf-8"))
except:
pass
You can use a module called subprocess import subprocess
Then you can define a variable like this
run = subprocess.run(command_to_execute, capture_output=True)
After that you can do print(run.stdout) to print the command output.
If you want to write it to a file you can do this after you run the above code
with open("PATH TO YOUR FILE", "w") as file:
file.write(run.stdout)
This should write a file which contains the output of your command
After that close the file using file.close() and reopen it but in "a" mode
with open("PATH TO YOUR FILE", "a") as file:
file.write(\n + run.stdout)
This should append data to your file.
Remember to close the file just for best practice, I have some bad memorys about not closing the file after I opened it :D
My plan is simple:
Open input, output file
Read input file line by line
Execute the command and direct the output to the output file
#!/usr/bin/env python3
import pathlib
import shlex
import subprocess
cmds_file = pathlib.Path(__file__).with_name("cmds.txt")
output_file = pathlib.Path(__file__).with_name("out.txt")
with open(cmds_file, encoding="utf-8") as commands, open(output_file, "w", encoding="utf-8") as output:
for command in commands:
command = shlex.split(command)
output.write(f"\n# {shlex.join(command)}\n")
output.flush()
subprocess.run(command, stdout=output, stderr=subprocess.STDOUT, encoding="utf-8")
Notes
Use shlex.split() to simulate the bash shell's command split
The line output.write(...) is optional. You can remove it
With subprocess.run(...), the stdout=output will redirect the command's output to the file. You don't have to do anything.
Update
I updated the subprocess.run line to redirect stderr to stdout, so error will show.

Python3: ValueError: I/O operation

I just want to make the print output redirect to a file. my code as below:
import sys
# define the log file that receives your log info
log_file = open("message.log", "w")
# redirect print output to log file
sys.stdout = log_file
print ("Now all print info will be written to message.log")
# any command line that you will execute
...
log_file.close()
print ("Now this will be presented on screen")
After execute the script, it comes an error:
[~/Liaohaifeng]$ python3 log.py
Traceback (most recent call last):
File "log.py", line 14, in <module>
print ("Now this will be presented on screen")
ValueError: I/O operation on closed file.
why does this happen? if I update my script as below:
import sys
# make a copy of original stdout route
stdout_backup = sys.stdout
# define the log file that receives your log info
log_file = open("message.log", "w")
# redirect print output to log file
sys.stdout = log_file
print ("Now all print info will be written to message.log"
# any command line that you will execute
...
log_file.close()
# restore the output to initial pattern
sys.stdout = stdout_backup
print ("Now this will be presented on screen")
It will be OK. So, could you please kindly tell me the theory in this issue?
As mentioned in comments, print does not print to a closed filehandle and you have closed sys.stdout, potentially breaking any prints evoked after it closed. Which may happen even without your knowledge, eg somewhere in the imported code. That's why you shouldn't fiddle with sys.* variables (or any variables you didn't create, really) unless you absolutely need to. There is a proper way to redirect print output to a file and it goes like this:
log_file = open('message.log', 'w')
print('Stuff to print in the log', file=log_file)
log_file.close()
Or even safer like this:
with open('message.log', 'w') as log_file:
# Do stuff
print('Stuff to print in the log', file=log_file)
The handle will automatically flush and close when the with block finishes.

Python file does not exist exception

I am trying to open a file and read from it and if the file is not there, I catch the exception and throw an error to stderr. The code that I have:
for x in l:
try:
f = open(x,'r')
except IOError:
print >> sys.stderr, "No such file" , x
but nothing is being printed to stderr, does open create a new file if the file name doesn't exist or is the problem somewhere else?
Try this:
from __future__ import print_statement
import sys
if os.path.exists(x):
with open(x, 'r') as f:
# Do Stuff with file
else:
print("No such file '{}'".format(x), file=sys.stderr)
The goal here is to be as clear as possible about what is happening. We first check if the file exists by calling os.path.exists(x). This returns True or False, allowing us to simply use it in an if statement.
From there you can open the file for reading, or handle exiting as you like. Using the Python3 style print function allows you to explicitly declare where your output goes, in this case to stderr.
You have the os.path.exists function:
import os.path
os.path.exists(file_path)
returns bool
It works for me. Why can't you make use of os.path.exists()
for x in l:
if not os.path.exists(x):
print >> sys.stderr , "No such file", x

python subprocess is overwriting file used for stdout - I need it to append to the file (windows)

I want to append the STDOUT of subprocess.call() to an existing file. My code below overwrites the file -
log_file = open(log_file_path, 'r+')
cmd = r'echo "some info for the log file"'
subprocess.call(cmd, shell=True, stdout=log_file, stderr=STDOUT)
log_file.close()
I'm looking for the equivalent of >> in subprocess.call() or subprocess.Popen(). It's driving me crazy trying to find it..
UPDATE:
Following the answers so far I've updated my code to
import subprocess
log_file = open('test_log_file.log', 'a+')
cmd = r'echo "some info for the log file\n"'
subprocess.call(cmd, shell=True, stdout=log_file, stderr=subprocess.STDOUT)
log_file.close()
I'm running this code from the command line in windows -
C:\users\aidan>test_subprocess.py
This adds the text to the log file. When I run the script again, nothing new is added. It still seems to be overwriting the file..
Use the 'a' append mode instead:
log_file = open(log_file_path, 'a+')
If you still see previous content overwritten, perhaps Windows needs you to explicitly seek to the end of the file; open as 'r+' or 'w' and seek to the end of the file:
import os
log_file = open(log_file_path, 'r+')
log_file.seek(0, os.SEEK_END)
Modify how you open log_file_path. You are opening the file for reading and writing 'r+'. Use the 'a' append mode instead of 'r+':
log_file = open(log_file_path, 'a+')

Using subprocess to log print statements of a command

I am running a Transporter command, which prints a log of what is happening to the prompt.
How would I re-direct all the print statements to a separate file called transporter_log.txt in the same folder as the script is running from? Something like -
log_file = open(PATH, 'w')
subprocess.call(shlex.split("/usr/local//iTMSTransporter -m verify...")
log_file.write(...)
You could specify the file as stdout parameter:
with open(PATH, 'wb') as log_file:
subprocess.check_call(cmd, stdout=log_file)
The output of cmd is written to log_file.
What about using the redirect command (in on unix)?
your_python.py > /path/to/transporter_log.txt

Categories