7

How can I capture output from Print from a function which does not leave the printed object as its final output, (and which I do not wish to edit)? E.g.

Module[{},
 Print[Plot[Sin[x], {x, 0, 2 Pi}]];
 a = 123]

I would like to use something like a temporary setting for $PrePrint or $Post, rather than use cell selection (SelectionMove, NotebookRead).

The aim is somehow to intercept the Print output -- the plot object -- and set it to a variable, (without altering the module).

This attempt did not work:-

enter image description here

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108

2 Answers2

9

I have found one solution, using a temporary file:-

streams = AppendTo[$Output, OpenWrite[]];

Module[{},
  Print[Plot[Sin[x], {x, 0, 2 Pi}]];
  a = 123];

Close@Last@streams;
$Output = Most@streams;
printoutput = ReadList@First@Last@streams

enter image description here

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108
  • This is great! Anyway to modify it so that the printed text is not outputted at all, but still captured to printoutput? – Kvothe Jun 16 '21 at 15:50
  • @Kvothe Yes, use Block as per Szabolcs' answer. (Writes to list.) – Chris Degnen Jun 16 '21 at 16:48
  • Thanks. I wrongly assumed that the Block method would not work for my case since the printed output is printed in python during ExternalEvaluate. Upon testing it does actually work so apparently these statements still get printed in Mathematica by internally using Print. – Kvothe Jun 17 '21 at 07:56
6

You can temporarily redefine Print, like so:

fun[] := Module[{}, Print[Plot[Sin[x], {x, 0, 2 Pi}]];
  a = 123]

list = {};
Block[{Print = AppendTo[list, {##}] &}, fun[]]

Now list contains everything that was printed. (Of course in a practical application you'd probably want to do something smarter than an inefficient periodic AppendTo)

If you still want to print the expressions while simultaneously saving them, use the Villegas-Gayley trick to redefine Print.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263