New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement autosave in notebook #1378
Comments
Thanks for the summary, this is indeed useful to track as it's a fairly self-contained question we've already discussed a fair bit. |
Yes, I think the basic features above would work fine for a first go. |
Some points I couldn't find in the threads (Just quickly read them. Sorry if I miss something):
|
On Mon, May 7, 2012 at 6:35 PM, Takafumi Arakaki
We are not even sure we want to use hidden files like this. Not too
Currently yes, this is unavoidable.
Brian E. Granger |
Just an idea. How about append the session id to the auto save file? |
On Tue, May 8, 2012 at 11:41 AM, Takafumi Arakaki
That is the problem though = we don't have any notion of sessions or
Brian E. Granger |
Can't we use Kernel.session_id?
|
Ah, maybe you want to separate kernel stuff from notebook. In that case, you will need "client id". But I guess defining it in client side and sending it to server won't be too hard. Well, if you want some more sophisticated session/user control it will be hard though. |
On Tue, May 8, 2012 at 11:55 AM, Takafumi Arakaki
Yes, the important session information is that of the notebook client,
Brian E. Granger |
I can only speak for UNIX/Linux, but on those systems, there is a long tradition and a lot of experience with how editors handle this. GNU Emacs started the conventions, but a lot of programs follow them now. Based on my experience, automatic backups, crash recovery, and source control are three different issues. Source control systems are not a replacement for backup or crash recovery files (otherwise people would have stopped using the latter long ago). There are conventions for how to do this, namely crash recovery files are of the form '##", and backup files are of the form " You may find these conventions ugly, and I might even agree, but it's both common usage, and it's a compromise between conflicting design goals. If you come up with your own convention, people won't know where to look for backup files, they won't know what the files are that you are leaving around, and they'll have to set up all their tools to deal with a different convention yet again. You also run the risk of breaking something; for example, using ".foo.ipynb" as a backup for "foo.ipynb" is potentially dangerous. |
@tmbdev, thanks for that comment; having used these features on *nix/emacs for over 15 years, I'd never given much thought to how they actually reflect a careful design process. Indeed a bit ugly filesystem-wise, but certainly not accidental. It's worth keeping this in mind, because if we want to break away from these conventions, at least we should do so aware of it and of the changes we introduce. |
I'd favour something more like how LibreOffice saves recovery files - out of the way, but readily accessible through the application (and presumably documented somewhere - we should document our location, anyway). Like us, it's a cross platform app, and Unix conventions don't necessarily work so well on Windows. |
As long as it's not as nagging as the libreoffice one is, that quite often has false positives that attempt recovery of non-existent stuff, and drives me nuts :) I'm not saying we must follow the *nix approach, just that this design background was very useful so we can keep them in mind as we approach the problem, and try to offer solutions to all the problem spectrum (even if our solutions end up being different today). |
I think the main annoyance with the LO design is that it's a modal dialog when it launches. I imagine something integrated with the file list, so if the autosave file was more recent than the saved version, it would offer:
So you can click the title for the last saved version, or the autosave line for the autosaved version. Obviously it would take a bit of tweaking to work out what's clearest - e.g. we might make the title line refer to the autosave, because 95% of the time that's what you want. |
For the current file based storage system we are currently using for notebooks, I actually like using something like "~" files in that directory. I agree that it is not pretty, but it is dead simple and matches the current philosophy of the notebook server that has absolutely no special databases or directories. |
If we can confirm that send2trash really works like is claims to I think we should put this in externals (we need to also check py3 compat) and use it instead of deleting files. |
send2trash appears to have gone for separate python 2/3 codebases: http://pypi.python.org/pypi/Send2Trash3k Although it looks like most of the changes could be handled by 2to3: |
Since we've been discussing this lately on the list, I figured I'd post here the easy python/JS solutions for user-driven autosave, for those who do want a regular autosave: One can enable autosave by putting this into the ipython startup file: def autosave(interval=5):
"""Autosave the notebook every interval (in minutes)"""
from IPython.core.display import Javascript
interval *= 60*1000 # JS wants intervals in miliseconds
tpl = 'setInterval ( "IPython.notebook.save_notebook()", %i );'
return Javascript(tpl % interval) and call it anywhere in the notebook to activate it. Alternately, just put this (in this case, using 5 minutes): <script type="text/javascript">
setInterval ( "IPython.notebook.save_notebook()", 5*60*1000 );
</script> in the first cell of a notebook and make it a markdown cell. Done, autosave is on for that notebook every time you open it. @shazow may be able to give us some tips on how to plug this into the browser saving machinery. |
My suggestion would be this: Implement the notebook auto-saving in the browser, and keep writing to a disk file on-demand. Here's how I'd do it: Add a little snippet of JavaScript which basically writes the current state of the notebook into the browser's LocalStorage every so often (assuming anything has changed). Not sure what the best way to dump the state is, could write the entire notebook JSON into a LocalStorage value blob—could even store revisions based on a timestamp key. If the browser crashes, we should still be able to recover the latest auto-saved version from LocalStorage and load the browser state accordingly. Then the user can manually save to a disk file as normal. Thoughts? |
Just be carefull that what Fernando gives this will overwrite you current saved file. Matthias // ~/.ipython/profile_default/static/js/custom.js
} // comment following line to disable. Le 12 nov. 2012 à 18:17, Fernando Perez a écrit :
|
Having autosave purely in the client avoids the potential for conflicts E.g. I'm working on a notebook at work, when my computer locks up. I recall I also see that the limits of localStorage are 2.5-10 MB, depending on the |
@takluyver, that's a good example, thank you. That is indeed confusing. Though perhaps better than losing your data altogether? The LocalStorage limits can be increased at the prompt of the user. |
"Having autosave purely in the client avoids the potential for conflicts when As far as I can tell, that case is already not working: saving in one The two choices for dealing with this are either to keep all the windows in Tom On Tue, Nov 13, 2012 at 2:37 AM, Thomas Kluyver notifications@github.comwrote:
|
@tmbdev: Agreed, we don't do anything to deal with such conflicts at present. But the problem would be more acute with autosaves. Imagine you left a notebook open on another computer (or even in another tab - I often have so many open that I forget some), and both the copy you're working on and the unedited copy have a naive autosave firing every minute. If you do suffer a crash/powercut/meteorite strike, it's pot luck whether the one you want got the last autosave. Come to think of it, using local storage actually wouldn't solve the case with two tabs open in the same browser. But maybe the solution to that is for me to pay attention to my tabs. ;-) |
With multiple windows open, the autosave would alternate between one and Data loss from multiple browser windows however is a real problem, that's On Tue, Nov 13, 2012 at 7:44 AM, Thomas Kluyver notifications@github.comwrote:
|
We will get to live syncing between browser/user. It is just not strait forward. |
I think we do need a simple autosave approach that will work for now. But, On Tue, Nov 13, 2012 at 2:35 AM, Bussonnier Matthias <
Brian E. Granger |
I'm new to iPython Notebooks and am very pleased with what I find - again I am indebted to an open source community - many thanks! For what it's worth, I have to agree with @tmbdev 's sentiments in #2553 - there is a conceptual simplicity with approaches like GoogleDocs and Dropbox: you are dealing with ONE virtual object, the same one wherever and however you access it. An important feature is the ability to rollback. This solves the issues around multiple versions and how/where to autosave as discussed here (both design complexity and confusion for the user). The traditional model of "don't hit save until you feel it's ready" is more suited to a version control paradigm like git (eg: @minrk's comment mentioned that 'save' could do a Thankyou @fperez for a way to set up autosave for those who want it now. |
Indeed, and there's even an extension I use regularly, so in my notebooks I just do:
to autosave every five minutes. It's quite trivial. |
I'll repost this as everybody forget it: Autosave overwrite current notebook, which is bad. even in VCS, we shouldn't do it.
|
Rather than auto-save, what about save-on-run? Every time you hit shift-enter (or some other shortcut) it saves the notebook and runs the cell. This would be the functional equivalent of working on the desktop, where you have to save your work before you execute it. |
It would be better to have "save on result back". The problem is every save can send a lot on the wire, so on every run could be really expensive. |
@fonnesbeck your idea can be implemented with this in an extension (or anywhere else): from IPython.display import display, Javascript
def savenb():
display(Javascript("IPython.notebook.save_notebook()"))
get_ipython().register_post_execute(savenb) (this will save after output is done, rather than immediately on execute) |
+1 to stash (aka mv) at least the prior version (perhaps hidden in the .ipython profile directory). Use case... wife deletes ipynb file by accident while on long trip with a lot of work done between backups. This is more important for the novice that the expert. More experienced users are likely to have other strategies (and might want to turn off the feature). On the mac, should would have bumped into the backup when desperately searching via spotlight/mdfind/find. |
I'm trying to implement something similar but slightly different: I want an auto-save option which saves a .py script, not the .ipnb file. The thought is to .gitignore *.ipnb files, tracking changes through these (much more readable in diffs) Python scripts in rapid development/prototyping. I have tried but cannot easily find a modification of any of the common Javascript hacks to allow .ipnb autosaving, nor can I find the Javascript API reference behind |
If you start the notebook with |
So if I use one of the standard Javascript hacks after starting with |
it will overwrite both - it will probably never be supported to export a notebook to a script without actually saving the notebook itself via public APIs, because the .py script is not a notebook - it is a lossy export of a notebook, |
It will owerwrite both. Le mardi 9 avril 2013, Josh Warner a écrit :
|
Thanks for the clarification, even if it's not what I'd hoped. Since the option exists to download the .py script individually (or it seemed so) from the interface, I incorrectly assumed this lossy export occured in memory and could operate independently. |
I think it's possible for the Python code (the server) to export a .py file On 9 April 2013 22:33, Josh Warner notifications@github.com wrote:
|
+1 to an integrated/by default auto-save. The solutions above are fine, but I think that this should still be implemented as something that is on by default. |
Autosave should be on by default on master. So should this issue still be open ? |
@Carreau - ok thanks, I'm using the latest stable so hadn't noticed. Great that it's implemented now! |
Nope, closing. |
I would just like to bring an older issue to the fore. This has been discussed on the mailing list (http://mail.scipy.org/pipermail/ipython-user/2012-January/009160.html) an in one of the issues it is also mentioned (#977), but I couldn't find an issue for it. I hope it is OK to raise again.
The consensus on the mailing list seemed to be that a simple autosave would be useful even before the implementation of a full-fledged revision control system, and it should have the following features:
Are these criteria still OK?
The text was updated successfully, but these errors were encountered: