|
19 | 19 |
|
20 | 20 | from . import _rpc |
21 | 21 | from . import util |
22 | | -from .stream import AsyncReader |
| 22 | +from .stream import AsyncReader, TextCallback |
23 | 23 |
|
24 | 24 |
|
25 | 25 | __all__ = [ |
@@ -172,10 +172,32 @@ def __init__(self, libmadx=None, command_log=None, stdout=None, |
172 | 172 | if stdout is None: |
173 | 173 | stdout = sys.stdout |
174 | 174 | if hasattr(stdout, 'write'): |
175 | | - try: |
176 | | - stdout = stdout.fileno() |
177 | | - except (AttributeError, OSError, IOError): |
| 175 | + # Detect if stdout is attached to a jupyter notebook: |
| 176 | + cls = getattr(stdout, '__class__', type(None)) |
| 177 | + qualname = cls.__module__ + '.' + cls.__name__ |
| 178 | + if qualname == 'ipykernel.iostream.OutStream': |
| 179 | + # In that case we want to behave the same way as `print` |
| 180 | + # (i.e. log to the notebook not to the terminal). On |
| 181 | + # linux, python>=3.7 within notebooks 6.4 `sys.stdout` has |
| 182 | + # a valid sys.stdout.fileno(), but writing to it outputs |
| 183 | + # to the terminal, so we have to use `sys.stdout.write()`: |
178 | 184 | stdout = stdout.write |
| 185 | + else: |
| 186 | + # Otherwise, let the OS handle MAD-X output, by passing |
| 187 | + # the file descriptor if available. This is preferred |
| 188 | + # because it is faster, and also because it means that the |
| 189 | + # MAD-X output is directly connected to the output as |
| 190 | + # binary stream, without potential recoding errors. |
| 191 | + try: |
| 192 | + stdout = stdout.fileno() |
| 193 | + except (AttributeError, OSError, IOError): |
| 194 | + stdout = stdout.write |
| 195 | + # Check for text stream to prevent TypeError (see #110). |
| 196 | + if callable(stdout): |
| 197 | + try: |
| 198 | + stdout(b'') |
| 199 | + except TypeError: |
| 200 | + stdout = TextCallback(stdout) |
179 | 201 | Popen_args['stdout'] = \ |
180 | 202 | subprocess.PIPE if callable(stdout) else stdout |
181 | 203 | # stdin=None leads to an error on windows when STDIN is broken. |
|
0 commit comments