Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have multiple dummy file writers in a with statement?

I read in this answer of Is it possible to have an optional with/as statement in python? that you can have a dummy file writer with contextmanager. I want, however, to open multiple dummy file writers in a with statement context.

Say I create two dummy files: touch a and touch b.

Given the first part of the script:

#!/usr/bin/python

from contextlib import contextmanager

# File names
fa="a"
fb="b"

# Dummy file handler
none_context = contextmanager(lambda: iter([None]))()

This addition works with a single dummy file writer (it prints 2):

printing=False
with (open(fa) if printing else none_context) as writter:
    print 1 if printing else 2

This also works, because we are indeed reading files (it prints 1):

printing=True
with (open(fa, "r") if printing else none_context) as writter, \
    (open(fb, "r") if printing else none_context) as another_writter:
    print 1 if printing else 2

However, it doesn't work if we are using two dummy file writers:

printing=False
with (open(fa, "r") if printing else none_context) as writter, \
    (open(fb, "r") if printing else none_context) as another_writter:
    print 1 if printing else 2

It shows the error:

Traceback (most recent call last):
  File "dummy_opener.py", line 23, in <module>
    with (open(fa, "r") if printing else none_context) as writter, \
  File "/usr/lib64/python2.7/contextlib.py", line 19, in __enter__
    raise RuntimeError("generator didn't yield")
RuntimeError: generator didn't yield

Why is this happening? And also: how can I make this multiple with open commands work with a dummy file writer?

like image 544
fedorqui 'SO stop harming' Avatar asked Dec 13 '25 18:12

fedorqui 'SO stop harming'


1 Answers

Your code fails as you have already consumed the iterator on the first call, if you call none_context() in the with block the original code would work:

none_context = contextmanager(lambda: iter([None]))
printing=False

with open(fa, "r") if printing else none_context() as writter, \
    open(fb, "r") if printing else none_context() as another_writter:
    print 1 if printing else 2

You can see using your original code that if you add a None for each open then the code will work as expected:

none_context = contextmanager(lambda: iter([None,None,None]))()
printing=False

with open(fa, "r") if printing else none_context as writter, \
    open(fb, "r") if printing else none_context as another_writter,\
    open(fb, "r") if printing else none_context as another_writer3:
    print 1 if printing else 2
like image 73
Padraic Cunningham Avatar answered Dec 16 '25 14:12

Padraic Cunningham



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!