[Python-ideas] Make Python code read-only

Steven D'Aprano steve at pearwood.info
Wed May 21 03:42:04 CEST 2014


On Wed, May 21, 2014 at 03:37:42AM +1000, Chris Angelico wrote:

> With that (rather big, and yet quite trivial) caveat, though: Looks
> interesting. Optimizing for the >99% of code that doesn't do weird
> things makes very good sense, just as long as the <1% can be catered
> for.

"99% of Python code doesn't do weird things..."

It seems to me that this is a myth, or at least unjustifiable by the 
facts as we have seen it. Victor's experiment shows 25 modules from the 
standard library are modifiable, with 139 read-only. That's more like 
15% than 1% "weird".

I don't consider setting sys.ps1 and sys.stdout to be "weird", which is 
why Victor has to leave sys unlocked.

Read-only by default would play havok with such simple idioms as global 
variables. (Globals may be considered harmful, but they're not 
considered "weird", and they're also more intuitive to many beginners 
than function arguments and return values. Strange but true.) As much as 
I wish to discourage people from using the global statement to rebind 
globals, I consider it completely unacceptable to have to teach 
beginners how to disable read-only mode before they've even mastered 
writing simple functions.

I applaud Victor for his experiment, and would like to suggest a couple 
of approaches he might like to think about. I assume that read-only mode 
can be set on a per-module basis.

* For simplicity, read-only mode is all-or-nothing on a per module 
basis. If the module is locked, so are the functions and classes defined 
by that module. If the module is not locked, neither are the functions 
and classes.

(By locked, I mean Victor's read-only mode where globals and class 
attributes cannot be re-bound, etc.)

* For backwards compatibility, any (eventual) production use of this 
would have to default to off. Perhaps in Python 4 or 5 we can consider 
defaulting to on.

* Define an (optional) module global, say, __readonly__, which defaults 
to False. The module author must explicitly set it to True if they wish 
to lock the module in read-only mode. There's no way to enable the 
read-only optimizations by accident, you have to explicitly turn them 
on.

* However there are ways to auto-detect when *not* to enable them. E.g. 
if a module uses the global statement in any function or method, 
read-only mode is disabled for that module.

* Similarly, a Python switch to enable/disable read-only mode. I don't 
mind if the switch --enable-readonly is true by defalt, so long as 
individual modules default to unlocked.


How about testing? It's very common, useful, and very much non-weird to 
reach into a module and monkey-patch it for the purposes of testing. I 
don't have a good solution to that, but a couple of stream of 
consciousness suggestions:

- Would it help if there was a statement "import unlocked mymodule" that 
forces mymodule to remain unlocked rather than read-only?

- Would it help if you could make a copy of a readonly module in an 
unlocked state?

- Obviously the "best" (most obvious) solution would be if there was a 
way to unlock modules on the fly, but Victor suggests that's hard.



-- 
Steven


More information about the Python-ideas mailing list