I started writing this blog in 2004 and, every year I published at least one post until 2022. So four years of not writing about Python ... and, actually, four years of (essentially) not writing any code. It is time for me to start writing and coding again, this time about a proposed new Python keyword: export.
Sources of frustration
- You change the names of some object intended for your private use only only to have users filing an issue, complaining that you broke their code.
- You try to ensure that your public names are well-documented by adding them to __all__ but find that this forces you to duplicate the information at two different locations leading you sometimes to forget to keep __all__ up to date.
- You read through the code of libraries you use but find it difficult to figure out which are meant to be public names and that you can safely use and which are meant to be purely private names since the required information is not immediately available where the objects are defined. Occasionally, you might see some names that begin with an underscore, which you know from convention that this is likely to indicate a private name ... but you cannot safely assume that names that do not begin with an underscore are meant to be public.
- You decide to use some type-based linters and find that you suddenly have to write code differently, such as from module import NAME as NAME instead of the perfectly simple and valid Python syntax, from module import NAME, only so that the stupid tool will understand your intention.
There are other related sources of frustration, but this should suffice to give you the context. To address these and related issues, three related PEPs have been written:
PEP 842, since withdrawn, was written first, and suggested many changes, including creating a new list named __export__, somewhat related to __all__, and which could be used to enforce a clear separation between public and private names. With the initial version of PEP 842, attempting to import a private variable would have resulted in an ImportError. PEP 842 also included the introduction of export as a new "soft" keyword, useable in the following five cases:
- Simple declaration: export NAME
- Assignment: export NAME = VALUE
- Declaring a function or class public: export def NAME() ... or export class NAME ...
- A module re-export statement: from MODULE export NAME
PEP 843 also suggested the introduction of export as a soft keyword, but focusing on indicating that names imported into a module were meant to be public.
This means that the following three types of statements:
from module export A [, B, ...]
from module export A as B, ....
from module export *
would behave like their corresponding from ... import statements with the exception that all the names imported would be automatically added to __all__, thereby ensuring that __all__ would always be kept up to date without needing any duplicate entry from the programmer. Furthermore, a user reading the source code would immediately see which names were meant to be made public.
PEP 844: instead of introducing an new keyword, PEP 844 suggests the addition of two functions from the publicly available atpublic to Python's builtins. This library includes two decorators, @public and @private, that can be used to indicate how these names are intended to be used; in addition, @public automatically adds the name of the function or class to __all__. Simple assignments can be also declared to be "public" using a cleverly built function.
The introductions of these PEPs has lead to many long discussion threads on Python-discuss (PEP 842 - discuss, PEP 842 - revision, PEP 842 - postmortem, PEP 843 - discuss, PEP 844 - discuss, General discussion about what public means in Python, and perhaps other).
For now the discussion seems to have died down.
Source of inspiration
As I mentioned previously, I have done almost no programming in the past four years. I still read about Python, but didn't have the motivation to actually write code. That is, until I read these discussions and pondered if it would not be possible to simply "try out this new syntax". This lead me to go back to working on a fun project , and write two new import hooks, documented here and here.
With these, you can try out right now what it would be like to use the proposed export keyword cases suggested in PEP 842 as well as in a subset of those suggested in PEP 843.
Go try it out, and let me know what you think!
In the meantime, I plan to continue working on ideas, and resume working on friendly/friendly-traceback as well as on Reeborg's World, and implementing many of the suggestions made by users over the past four years.