5

I'm trying to have the output of a python script be sourceable. i.e. I'd like to be able to run:

$ source <(python example.py)

It ALWAYS fails with the same issue:

Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>
BrokenPipeError: [Errno 32] Broken pipe

Here is example.py:

print("export ENV_VAR=abc")

Is there any way around this? I've attempted to try and catch the exception (BrokenPipeError) but it doesn't seem to work. The exception seems to prevent the sourcing from working since

$ echo $ENV_VAR

gives me nothing

9000
  • 39,899
  • 9
  • 66
  • 104
Bryant
  • 3,011
  • 1
  • 18
  • 26
  • 2
    This could be a [open issue](https://bugs.python.org/issue11380,#msg153320) in Python – Inian Dec 20 '17 at 16:19
  • Your example works fine in my shell (bash on Cygwin). – jbch Dec 20 '17 at 16:19
  • I should mention this is python 3.6 on macOS – Bryant Dec 20 '17 at 16:28
  • 1
    On macOS, the same happens with Python 2.7. On Linux, it works. – 9000 Dec 20 '17 at 20:41
  • This sounds like it might be a buffering issue. Does adding `sys.stdout.flush()` as the very last line of `example.py` make a difference? I was able to mock up something that reproduced this behaviour with named pipes in Linux, and flushing solved the problem. – Dunes Dec 21 '17 at 12:10
  • I did try flushing `stdout` and it did not solve the issue – Bryant Dec 21 '17 at 13:24

2 Answers2

1

Maybe eval or export could be used to get the variables from a Python script into the current Bash environment:

export $( python example.py )
echo $ENV_VAR

...or...

eval $( python example.py )
echo $ENV_VAR

There might be a better way to handle this, although both should output "abc".

l'L'l
  • 44,951
  • 10
  • 95
  • 146
  • you can simply use `$(python example.py)` and it does work, but for my use case, that isn't good enough. I'd like to have the script give output so if you run it incorrectly (i.e. missing the `source`) it can print output so you know you need to run it a different way. (i.e. `print("# You need to run the command like so ....")`). If you have something like that with the `$()` method, it wont work. It should/would work with `source <(...)` – Bryant Dec 21 '17 at 13:26
  • Maybe report the behavior as a bug perhaps, since it doesn’t seem correct as of now. – l'L'l Dec 21 '17 at 18:11
0

You can fix it in the python script or by sending the output of the python script to a program that does not freak out when its stdout is closed.

source <(python example.py | tee -p /dev/null)

Side note: I could not get source to reproduce the error described, but I was able to replicate the problem using echo

hackerb9
  • 1,545
  • 13
  • 14