Marco
Marco

Reputation: 88

Subprocess error file

I'm using the python module subprocess to call a program and redirect the possible std error to a specific file with the following command:

with open("std.err","w") as err:
    subprocess.call(["exec"],stderr=err)

I want that the "std.err" file is created only if there are errors, but using the command above if there are no errors the code will create an empty file. How i can make python create a file only if it's not empty?

I can check after execution if the file is empty and in case remove it, but i was looking for a "cleaner" way.

Upvotes: 6

Views: 305

Answers (2)

Padraic Cunningham
Padraic Cunningham

Reputation: 180391

You could use Popen, checking stderr:

from subprocess import Popen,PIPE

proc = Popen(["EXEC"], stderr=PIPE,stdout=PIPE,universal_newlines=True)

out, err = proc.communicate()
if err:
    with open("std.err","w") as f:
        f.write(err)

On a side note, if you care about the return code you should use check_call, you could combine it with a NamedTemporaryFile:

from tempfile import NamedTemporaryFile
from os import stat,remove
from shutil import move

try:
    with NamedTemporaryFile(dir=".", delete=False) as err:
        subprocess.check_call(["exec"], stderr=err)
except (subprocess.CalledProcessError,OSError) as e:
    print(e)


if stat(err.name).st_size != 0:
    move(err.name,"std.err")
else:
    remove(err.name)

Upvotes: 2

bgporter
bgporter

Reputation: 36454

You can create your own context manager to handle the cleanup for you -- you can't really do what you're describing here, which boils down to asking how you can see into the future. Something like this (with better error handling, etc.):

import os
from contextlib import contextmanager

@contextmanager
def maybeFile(fileName):
   # open the file
   f = open(fileName, "w")
   # yield the file to be used by the block of code inside the with statement
   yield f
   # the block is over, do our cleanup.
   f.flush()
   # if nothing was written, remember that we need to delete the file.
   needsCleanup = f.tell() == 0
   f.close()
   if needsCleanup:
      os.remove(fileName)

...and then something like:

with maybeFile("myFileName.txt") as f:
   import random
   if random.random() < 0.5:
      f.write("There should be a file left behind!\n")

will either leave behind a file with a single line of text in it, or will leave nothing behind.

Upvotes: 0

Related Questions