Often I need to output data either to file or, if file is not specified, to stdout. I use the following snippet:
JavaScript
x
6
1
if target:
2
with open(target, 'w') as h:
3
h.write(content)
4
else:
5
sys.stdout.write(content)
6
I would like to rewrite it and handle both targets uniformly.
In ideal case it would be:
JavaScript
1
3
1
with open(target, 'w') as h:
2
h.write(content)
3
but this will not work well because sys.stdout is be closed when leaving with
block and I don’t want that. I neither want to
JavaScript
1
3
1
stdout = open(target, 'w')
2
3
because I would need to remember to restore original stdout.
Related:
- Redirect stdout to a file in Python?
- Handling Exceptions – interesting article about handling exceptions in Python, as compared to C++
Edit
I know that I can wrap target
, define separate function or use context manager. I look for a simple, elegant, idiomatic solution fitting that wouldn’t require more than 5 lines
Advertisement
Answer
Just thinking outside of the box here, how about a custom open()
method?
JavaScript
1
16
16
1
import sys
2
import contextlib
3
4
@contextlib.contextmanager
5
def smart_open(filename=None):
6
if filename and filename != '-':
7
fh = open(filename, 'w')
8
else:
9
fh = sys.stdout
10
11
try:
12
yield fh
13
finally:
14
if fh is not sys.stdout:
15
fh.close()
16
Use it like this:
JavaScript
1
15
15
1
# For Python 2 you need this line
2
from __future__ import print_function
3
4
# writes to some_file
5
with smart_open('some_file') as fh:
6
print('some output', file=fh)
7
8
# writes to stdout
9
with smart_open() as fh:
10
print('some output', file=fh)
11
12
# writes to stdout
13
with smart_open('-') as fh:
14
print('some output', file=fh)
15