Our idea is not &quot;notebook as dir&quot; but &quot;project as dir/repo&quot;, where a project contains any of: notebooks, data files, Python modules, etc.<div><br></div><div>I don&#39;t think storing binary data in the notebook file itself is worth a new kernel-side API, more than existing systems for b64 data in Python scripts, which will work just as well in the notebook as anywhere else (not that they are great, of course).</div>

<div><br></div><div>We did seriously consider the idea of archive file-formats while planning the notebook format, but we decided (largely from the perspective of VCS, etc) that JSON makes much more sense, and data files belong at the project level.  For instance, what if you want two notebooks to work on the same data? The data shouldn&#39;t live in either notebook, nor in both.</div>

<div><br></div><div>What is unfortunate at this point is that we really haven&#39;t developed our project-level UI/APIs yet, they only exist in the planning stages.  I think once you have project as dir/repo, then the benefits of data in the notebook file itself vanish, as the project becomes the unit of sharing/etc.  We would certainly have the ability to support *project* as a zipfile, that gets extracted on upload to the server.</div>

<div><br></div><div>-MinRK<br><br><div class="gmail_quote">On Tue, Jun 5, 2012 at 12:21 PM, Brian Granger <span dir="ltr">&lt;<a href="mailto:ellisonbg@gmail.com" target="_blank">ellisonbg@gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">You could also use the %%file magic that is under review here:<br>
<br>
<a href="https://github.com/ipython/ipython/pull/1855" target="_blank">https://github.com/ipython/ipython/pull/1855</a><br>
<div class="HOEnZb"><div class="h5"><br>
On Tue, Jun 5, 2012 at 12:10 PM, Thomas Breuel &lt;<a href="mailto:tmbdev@gmail.com">tmbdev@gmail.com</a>&gt; wrote:<br>
&gt; I should say that the nb_open and nb_data interfaces I&#39;m suggesting are<br>
&gt; independent of the storage format, so adopting them now for a JSON based<br>
&gt; storage would be safe even if the storage format changes to something else<br>
&gt; in the future.<br>
&gt;<br>
&gt; Tom<br>
&gt;<br>
&gt;<br>
&gt; On Tue, Jun 5, 2012 at 9:09 PM, Thomas Breuel &lt;<a href="mailto:tmbdev@gmail.com">tmbdev@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi,<br>
&gt;&gt;<br>
&gt;&gt; thanks for the response.<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Our vision is &#39;folder as a project&#39; - so the code in a notebook sits<br>
&gt;&gt;&gt; alongside data files, keeping the notebook file lightweight and<br>
&gt;&gt;&gt; suitable for version control.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Well, right now the notebook is a file in JSON format, but it already<br>
&gt;&gt; includes binary data in encoded form.  I&#39;m just suggesting a small addition<br>
&gt;&gt; that would make this existing storage facility useful for storing modest<br>
&gt;&gt; amounts of extra data.<br>
&gt;&gt;<br>
&gt;&gt; If you do want to change the notebook format in the future, I think that&#39;s<br>
&gt;&gt; worth considering; see my suggestion at the very end.<br>
&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; I can see there&#39;s an argument for having a way to store data as part<br>
&gt;&gt;&gt; of a notebook, but I think there are some questions:<br>
&gt;&gt;&gt; - How would the user interface work: How would the data be brought in<br>
&gt;&gt;&gt; and assigned to a variable? What would be displayed in the notebook?<br>
&gt;&gt;&gt; Would we handle different types of files differently, or treat all<br>
&gt;&gt;&gt; binary files the same?<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; A simple interface might be the following:<br>
&gt;&gt;<br>
&gt;&gt; stream = nb_open(&quot;some/path/to/my.data&quot;)<br>
&gt;&gt;<br>
&gt;&gt; data = nb_data(&quot;mydata&quot;,lambda:randn(100))<br>
&gt;&gt;<br>
&gt;&gt; nb_open opens a stream to the data cached in the notebook, unless that<br>
&gt;&gt; data doesn&#39;t exist; in that case, it caches the file in the notebook and<br>
&gt;&gt; then opens it.  It always returns just a stream.<br>
&gt;&gt;<br>
&gt;&gt; nb_data gets data from the notebook if it has been stored there; if not,<br>
&gt;&gt; it calls its second argument, stores the result in the notebook, and also<br>
&gt;&gt; returns it.<br>
&gt;&gt;<br>
&gt;&gt; This interface means that as an author, I just write the code, maybe clear<br>
&gt;&gt; the notebook cache a few times, but I don&#39;t even have to think about<br>
&gt;&gt; managing the notebook data; if my notebook works once, it will continue to<br>
&gt;&gt; work indefinitely even if the file or data become unavailable (until I clear<br>
&gt;&gt; the notebook data explicitly).<br>
&gt;&gt;<br>
&gt;&gt; See the low-level code below.<br>
&gt;&gt;<br>
&gt;&gt; (There should be a UI button and another function for clearing the<br>
&gt;&gt; cache/data stored in the notebook.)<br>
&gt;&gt;<br>
&gt;&gt;&gt; - How would performance hold up? We&#39;d have to base64 encode the data<br>
&gt;&gt;&gt; to store it in JSON, so loading binary data will inevitably be slower<br>
&gt;&gt;&gt; as it has an extra decoding step. It also increases the size of the<br>
&gt;&gt;&gt; data on disk.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Obviously, this doesn&#39;t solve all data storage problems.  But many<br>
&gt;&gt; educational notebooks just need an image or a small dataset, and having an<br>
&gt;&gt; easy way of storing such moderate amounts of data in the notebook would be<br>
&gt;&gt; nice, in particular since the notebook already stores comparable kinds and<br>
&gt;&gt; amounts of data for the outputs.<br>
&gt;&gt;<br>
&gt;&gt;&gt;  - Is the cost/benefit trade off worth it? This may involve significant<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; extra complexity in IPython, and it&#39;s simple enough to zip up a<br>
&gt;&gt;&gt; notebook file + input data.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; I think this can probably piggy-back on existing mechanisms.  I think you<br>
&gt;&gt; need two low-level Python functions: nb_get_binary_data(key) and<br>
&gt;&gt; nb_put_binary_data(key,value).  The first one sends a message to the<br>
&gt;&gt; notebook asking whether there is binary data for the given key and returns<br>
&gt;&gt; it or returns None, and the second one stores binary data under the given<br>
&gt;&gt; key.    I think those should be pretty easy to provide, since the same kind<br>
&gt;&gt; of thing already needs to happen for output cells.<br>
&gt;&gt;<br>
&gt;&gt; In terms of those primitives, nb_open looks roughly like:<br>
&gt;&gt;<br>
&gt;&gt; def nb_open(path,mode=&quot;r&quot;):<br>
&gt;&gt;     assert mode==&quot;r&quot;,&quot;cached files need to be read-only for now&quot;<br>
&gt;&gt;     key = &quot;file:&quot;+path<br>
&gt;&gt;     data = nb_get_binary_data(key)<br>
&gt;&gt;     if data is None:<br>
&gt;&gt;         with open(path) as stream: data = stream.read()<br>
&gt;&gt;         nb_put_binary_data(key,data)<br>
&gt;&gt;     return data_as_stream(data,&quot;r&quot;)<br>
&gt;&gt;<br>
&gt;&gt; The nb_data(name,thunk) function would be pretty similar.<br>
&gt;&gt;<br>
&gt;&gt; Tom<br>
&gt;&gt;<br>
&gt;&gt; PS: As for the &quot;notebook as directory&quot;, having notebooks be single files<br>
&gt;&gt; is quite convenient, since zipping/unzipping things and dealing with<br>
&gt;&gt; directories can be a nuisance in many settings.  What you could do in the<br>
&gt;&gt; future, however, is allow notebooks to be either directories or zip files<br>
&gt;&gt; containing a directory tree, making the difference as transparent to the<br>
&gt;&gt; notebook and user.  I think that would be a great direction to go into, also<br>
&gt;&gt; because you could then store the output images separate from the pure text.<br>
&gt;&gt;  Note that OpenOffice and OpenDocument files work that way, and data files<br>
&gt;&gt; could also be embedded efficiently. Furthermore, version control tools are<br>
&gt;&gt; starting to be able to deal with document formats based on zip files.  But,<br>
&gt;&gt; in any case, that&#39;s a bigger change than what I suggested above.<br>
&gt;&gt;<br>
&gt;&gt; For ZIP files as document formats, see<br>
&gt;&gt; <a href="http://www.openoffice.org/xml/faq.html" target="_blank">http://www.openoffice.org/xml/faq.html</a> and <a href="http://en.wikipedia.org/wiki/OpenDocument" target="_blank">http://en.wikipedia.org/wiki/OpenDocument</a><br>


&gt;&gt;<br>
&gt;&gt; Here is Mercurial version control for ZIP-based document<br>
&gt;&gt; formats: <a href="http://mercurial.selenic.com/wiki/ZipdocExtension" target="_blank">http://mercurial.selenic.com/wiki/ZipdocExtension</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
</div></div><div class="im HOEnZb">&gt; _______________________________________________<br>
&gt; IPython-User mailing list<br>
&gt; <a href="mailto:IPython-User@scipy.org">IPython-User@scipy.org</a><br>
&gt; <a href="http://mail.scipy.org/mailman/listinfo/ipython-user" target="_blank">http://mail.scipy.org/mailman/listinfo/ipython-user</a><br>
&gt;<br>
<br>
<br>
<br>
</div><span class="HOEnZb"><font color="#888888">--<br>
Brian E. Granger<br>
Cal Poly State University, San Luis Obispo<br>
<a href="mailto:bgranger@calpoly.edu">bgranger@calpoly.edu</a> and <a href="mailto:ellisonbg@gmail.com">ellisonbg@gmail.com</a><br>
</font></span><div class="HOEnZb"><div class="h5">_______________________________________________<br>
IPython-User mailing list<br>
<a href="mailto:IPython-User@scipy.org">IPython-User@scipy.org</a><br>
<a href="http://mail.scipy.org/mailman/listinfo/ipython-user" target="_blank">http://mail.scipy.org/mailman/listinfo/ipython-user</a><br>
</div></div></blockquote></div><br></div>