Posts: 4,646
Threads: 1,493
Joined: Sep 2016
i have a big block of code the i do not want to duplicate. in one case i want the block to be done with f as an opened file that gets closed at the end. in the other case it should output to stdout without closing stdout. at first i did it like this: for name in all_the_names:
with stdout if 'stdout' in options else open(f'{name}.log','w') as f:
...
print(...,file=f) # many lines of code here, do not copy
... then i realized that the with might cause stdout to be closed. would that really happen? if so, how can i avoid that?
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 4,782
Threads: 76
Joined: Jan 2018
Nov-02-2019, 12:45 AM
(This post was last modified: Nov-02-2019, 12:47 AM by Gribouillis.)
A contextmanager should do the trick (to be tested)
from contextlib import contextmanager
import sys
@contextmanager
def outfile(name, use_stdout):
if use_stdout:
yield sys.stdout
else:
with open(f'{name}.log', 'w') as f:
yield f
for name in all_the_names:
with outfile(name, stdout in options) as f:
print('Spam', file=f)
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
Nov-02-2019, 03:50 AM
(This post was last modified: Nov-02-2019, 03:50 AM by Skaperen.)
could that work for this other thing i want do? i want to be able to open and write a file with a temporary name of my choice and when with closes it, it also gets renamed to the permanent name.
for name in names:
t = int(time.time()*3906250)
with tmpopen(f'{name}-(t)',name,'w') as f
print('#!/usr/bin/env python3',file=f)
print('# put your code here:',file=f)
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 4,782
Threads: 76
Joined: Jan 2018
Skaperen Wrote:could that work for this other thing i want do? Of course it would, you only need to rename the file after the 'with open...' block in the contextmanager. But I think we already discussed this problem in the forum and we wrote a solution somewhere.
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
i want to do it within the with statement so that it is sure to happen (or at least be attempted). sure, i can do it after the with. i can close the file after the with, too. the justification for using with to do a close ... i want to use for doing the rename, too. so i would expect a method that returns an object with a context manager that takes care of both the close and the rename.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 4,782
Threads: 76
Joined: Jan 2018
It is after the with statement in the context manager but it is included in the with statement for the code that uses the contextmanager.
Posts: 4,646
Threads: 1,493
Joined: Sep 2016
i thought with called some special method on the file(-like) object used in the with statement that does a close on the file.
Tradition is peer pressure from dead people
What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Posts: 4,782
Threads: 76
Joined: Jan 2018
Nov-03-2019, 07:28 AM
(This post was last modified: Nov-03-2019, 07:28 AM by Gribouillis.)
Skaperen Wrote:i thought with called some special method on the file(-like) object used in the with statement that does a close on the file.
In the statement
with foo as bar:
spam() bar is not foo , it is the value returned by foo.__enter__() which can be anything, including a file object. At the end of the with statement's execution, no method is called on bar , but the method foo.__exit__() is called.
It often happens that foo and bar are the same object, for example when foo is the result of a call to open() . The __exit__() method on a file object calls the close() method, but in general you can program whatever behaviour at a block's exit, even if bar is a file object.
Posts: 2,122
Threads: 10
Joined: May 2017
Nov-03-2019, 07:52 AM
(This post was last modified: Nov-03-2019, 07:53 AM by DeaD_EyE.)
The use of a context manager together with sys.stdout does not make much sense, because the fd is open until the program ends.
import os
with os.fdopen(sys.stdout.fileno(), 'w', closefd=False) as fd:
fd.write('Hello World\n')
# is still open
sys.stdout.write('Hello World\n')
Posts: 4,782
Threads: 76
Joined: Jan 2018
It makes sense here because Skaperen wants the same client code whether he uses stdout or a regular file. It's an API normalization.
|