2

I'm trying to redirect an output from a shell window opened from a python script - to a file.

So, after some googling, I came up with this code:

file_output = open(MS_Log + 'LOGS.txt', 'w+')
subprocess.call('start ' + URL_logs, shell=True, stdout=file_output)

This does indeed opens a new shell window and runs the command I want in it. However, the output is printed on the screen (inside that new shell window) and not to the file.

I want it to be both - printed in the shell window and saved to file.

Now, the command I run there is continuous, it runs until stopped with Ctrl+C, so I think this might be the problem...? Maybe if it will be closed gracefully it will dump it's contents to the file?

jfs
  • 399,953
  • 195
  • 994
  • 1,670
Alexy Grabov
  • 151
  • 1
  • 13
  • @Daniel Sanchez I did, if you read through you will see that I did the search, tried to code it myself & said what actually happens vs. what I want to achieve. – Alexy Grabov Mar 30 '16 at 14:14
  • better focused question: [getting output to file from python subprocess with 'start'](http://stackoverflow.com/q/36328579/4279) – jfs Mar 31 '16 at 20:05

2 Answers2

1

You can try to save the output in a variable and then write this in a file:

process = subprocess.Popen(command, stdout = subprocess.PIPE, shell = True)
(process_output,  error) = process.communicate()
file = open(path_of_file_output, "w")
file.write(process_output)
file.close()
Miguel Jiménez
  • 484
  • 2
  • 12
  • 1
    Maybe add a line about why `shell = True` can be a security issue? – jDo Mar 30 '16 at 07:30
  • He want that the output will show in the terminal, if you don't want that show the output you put `Shell = False` and solved – Miguel Jiménez Mar 30 '16 at 07:38
  • Thanks @Miguel Jiménez. I tried this code (with a simple echo, instead of a complex command, so I can be sure it ends), and it still doesn't write to the file. `process = subprocess.Popen('start echo hello', stdout = subprocess.PIPE, shell = True) (process_output,  error) = process.communicate() file = open('LOGS.txt', "w") file.write(process_output) file.close() ` – Alexy Grabov Mar 30 '16 at 14:10
  • Why do you write `start echo hello`? You write only `echo hello`. Popen execute terminal commands, the word 'start' isn't correct here. – Miguel Jiménez Mar 30 '16 at 20:54
  • @MiguelJiménez OP seems to be on a Windows system where `start` is a valid command that, you guessed it, starts an external process/program. [More on that here](http://www.robvanderwoude.com/ntstart.php). I'm on a *nix system and I assume you are too since `echo hello` would be valid in shell/bash. – jDo Mar 30 '16 at 21:09
  • I've indeed come to the conclusion that the problem here is with 'start'. Without it, it works fine - but doesn't open a new CMD window. Any ideas...? – Alexy Grabov Apr 03 '16 at 09:22
0

OP, I adapted a good solution from this question.

It should show the output of your command in terminal and save it to file while running. That means it'll work for infinite loops as well. It doesn't use the shell=True option that leaves you open to shell injection (always set tight permissions on a script that uses shell=True if you're not just playing on your LAN at home). The solution has one weakness: it only works if there are newlines in your output; if not, nothing will be printed/written.

import subprocess

""" continuously print command output and append it to file while running """

def run(command):    
    popen = subprocess.Popen(command, stdout=subprocess.PIPE)
    return iter(popen.stdout.readline, b"")

filename = "subprocess_output"
f = open(filename, "a")

for line in run(["/bin/bash", "infinite_loop.sh"]):
    print(line), # the comma keeps python from adding an empty line
    f.write(line)

f.close()
jDo
  • 3,962
  • 1
  • 11
  • 30
  • Thanks, I'll try it in a few min and update with the results! – Alexy Grabov Mar 30 '16 at 14:14
  • This indeed creates a file and writes to it, however, it stops working when I add 'start' to the command prompt (which I need in order to open a new CMD window). I think I might just use this solution (if I won't figure out how to make it work like I want to), and just pop a CMD window for display purpose only, i.e. I will run the command twice - once in the new CMD window, and one time w\o the new window - just to save the output. – Alexy Grabov Apr 03 '16 at 09:21
  • @AlexyGrabov There are probably ways to do it but I still haven't found the perfect solution. On another note, why is it necessary to open another terminal window instead of keeping the output in the window that runs the script? – jDo Apr 03 '16 at 14:04
  • Because I want to open 3-4 windows, and show different scrolling logs in all of them. If I do this in one window it will be messy :) – Alexy Grabov Apr 04 '16 at 06:49