43

I would like to be able to save the TEXT output of an iPython notebook cell into a file on disk.

I have 2 additional requirements/requests:

  • be able to re-run the cell and overwrite my output with whatever the latest is.
  • also display the output within the notebook.

I have figured out how to use the %%capture magic for some basic saving of an iPython notebook's cell into a file, but it does not seem flexible enough: it keeps appending every time I re-run the cell and I cannot get it to display within the same cell.

Here is what I have so far:

%%capture cap --no-stderr
print 'stuff'
with open('output.txt', 'w') as f:
    f.write(cap.stdout)

# clear the cap by deleting the variable here?
# del cap 

When I try to put cap.show() after the write, it does not seem to display. Instead, it puts the output into the cap variable twice.

Marioanzas
  • 1,663
  • 2
  • 10
  • 33
pocketfullofcheese
  • 8,427
  • 9
  • 41
  • 57
  • 1
    Do you want *all* textual output or just the one created by the print statements? Due to the IPython display machinery all objects have a textual representation, so there is more text in the notebook than visible in the first place. – Jakob Jan 18 '15 at 07:52
  • 1
    If you are just after the print statements, have a look at the answers to [this question](http://stackoverflow.com/q/11325019/2870069) – Jakob Jan 18 '15 at 07:54
  • This maybe useful for saving specific cells: https://datascience.stackexchange.com/questions/13669/how-to-export-one-cell-of-a-jupyter-notebook – Pierz Apr 08 '19 at 14:20

3 Answers3

42

You have a typo, missing d in cap.stout. It should be cap.stdout I tested the following and it worked fine. cap.show() also printed "stuff" and re-running the cell overwrote the file.

%%capture cap --no-stderr
print 'stuff'
with open('output.txt', 'w') as f:
    f.write(cap.stdout)
Amit
  • 19,780
  • 6
  • 46
  • 54
  • fixed the typo. It was only in the question, not in my source code. The overwriting is fine, the problem is that it sometimes duplicates the output if you don't do "del cap". Or if you add cap.show(), it prints it to the file twice (instead of once to file and once on screen) – pocketfullofcheese Jan 16 '15 at 23:30
  • 1
    that is, the problem isn't overwriting the file (opening with 'w' will clear the file). The problem is that the cap variable does not get cleared between runs. – pocketfullofcheese Jan 16 '15 at 23:30
  • 1
    Running `cap.show()` in different cell will not write to the file. – Amit Jan 16 '15 at 23:35
  • 7
    Every time I run this command for the first it gives an error saying `name cap doesn't exist`. The second time I run it, it executes fine. – BND May 08 '19 at 16:07
  • I have the same problem as BND. – Matthew Jul 10 '19 at 15:09
  • 4
    I think you cannot access `cap` until the cell finished executing – Sdra Aug 23 '19 at 14:12
  • 5
    Indeed, `with open('output.txt', 'w') as f: f.write(cap.stdout)`has to be in another cell. – Delforge Oct 22 '20 at 13:47
1
%%capture cap --no-stderr
print("a")
with open('output.txt', 'w') as f:
    f.write(str(cap))
  • 3
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Jeroen Steenbeeke Feb 02 '21 at 07:08
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/low-quality-posts/28223470) – Atish Agrawal Feb 02 '21 at 07:14
  • @AtishAgrawal: What makes you say that? This certainly looks like an answer to me. Yes, it’s light on explanation, as Jeroen noted, but it’s still an answer. – Jeremy Caney Feb 02 '21 at 08:10
  • @JeremyCaney If you look carefully, the following answer by Amit Verma, he had answered it well before this person. This person seems a plain old copy of the answer which has been upvoted 30 times. Don't you think the core motive of the above answer is to gain experience on SO? Give it a thought. Also, pasting code snippet is never a good answering strategy on SO. You must include a bit of explanation along with the code piece. (Which in turn is done by Amit Verma). New users should learn the best practices of QnA at SO. – Atish Agrawal Feb 02 '21 at 11:51
  • 1
    @AtishAgrawal: First, if you look _really_ closely, you’ll see it’s not actually duplicate code; they’ve identified a different proposal without calling `stdout`. Second, while code-only answers are certainly _discouraged_, [they’re not subject to _removal_](https://meta.stackoverflow.com/questions/287563/youre-doing-it-wrong-a-plea-for-sanity-in-the-low-quality-posts-queue). The appropriate action here is to downvote the answer. That’s how we incentivize following best practices when users make a sincere attempt to answer, but don’t offer a sufficiently detailed or useful contribution. – Jeremy Caney Feb 02 '21 at 18:23
0

%%capture cap captures different outputs of the current cell (depending on --no-stderr, --no-stdout, or --no-display options) and stores them in cap.

The capture object cap is only created/updated at the end of the cell execution. To display its content, using cap() (same as cap.show()), or save it to a file, you have to do it in another cell.

In a first cell, cap is filled with output contents, and in a second cell cap content is saved and displayed:

%%capture cap
del cap # delete previously existing cap variable 
print("capture me if you can!")

with open('output.txt', 'w') as f:
    f.write(cap.stdout)
cap()

capture me if you can!

When %%capture cap, cap.stdout, and cap.show() are all in the same cell:

%%capture cap
del cap # delete previously existing cap variable
print("capture me if you can!")
with open('output.txt', 'w') as f:
    f.write(cap.stdout)
cap()

it raises a NameError: name 'cap' is not defined error.

If it does not raise an error, that means that you had already initialized cap with some data (maybe running the very same cell but without the cap.output and cap.show()).
In that case, that means that by adding cap.show() at the end of your cell, you add the content of cap to the outputs of this cell, so, you override cap content with "the new output of the cell + the previous content of cap".
As a result, the next time you will run the cell it will write in your file the previous "new output of the cell + previous content of cap".

Note that, in the examples above, the del cap is just here to raise errors when cap is called in the %%capture cap cell. This del cap is not necessary for normal use: cap's content is fully replaced when %%capture cap is called.

Ken
  • 442
  • 5
  • 11