It's difficult to differentiate between code errors and network errors reliably at this point. So rather than swallowing all exceptions and trying again, we'll log all exceptions and try again, allowing the system administrator to sort out which ones are false positives.
Previously, open() wasn't accepting *args (only **kwargs), which caused crashes when called as foo.open(filename, "r"), for example. Also, it was only attempting to open the locally saved copy, which may not even exist for something that has already been sent to remote storage. So now we try remote first and then local, the same as for all the other methods.
This drastically speeds up startup times for anything that imports all models (which is pretty much anything in Django). It saves having to connect to the remote storage, in particular, until it's required.