On 2/9/07, Josiah Carlson <jcarlson@uci.edu> wrote:
"Brett Cannon" <brett@python.org> wrote:
On 2/9/07, Josiah Carlson <jcarlson@uci.edu> wrote:
"Brett Cannon" <brett@python.org> wrote:
On 2/9/07, Ron Adam <rrr@ronadam.com> wrote: [snip]
import module module()
And it would just work. ;-)
I like this idea. Makes it very obvious. You just say "when a specific module is specified at the command line it is called. Could even have it take possibly sys.argv[1:] (which I think was supposed to turn into sys.args or sys.arg or something at some point).
What do other people think?
I don't like it. Much of my dislike comes from personal aesthetics, but then there is a logical disconnect. When an instance of a class is created, its __call__ method is not automatically called. By using the semantic of 'the __call__ function in the module namespace is automatically executed if the module is "run" from the command line', we are introducing a different instance creation semantic (an imported module is an instance of ModuleType).
But I don't see the leap of how specifying a module to execute on the command line is any different than doing ``Class()()`` for instantiation with an immediate call. It would still be a separate step.
I feel that there is a disconnect, but maybe it's personal aesthetics again.
I think we should just stick with what has been proposed for *years*, a __main__ function that is automatically executed after the module has been imported if its __name__ == '__main__'.
But that does not solve the problem Ron has been trying to deal with; setting __name__ to __main__ prevents the execution of a module that uses relative imports because the import machinery can then no longer infer what package the module is in.
I may have missed it, but how are either of the following ambiguous...
from . import foo from ..bar import baz
The leading dot tells me that 'relative to the path of the current module (or __init__.py module in a package), look for packages/modules named [everything else without a single leading dot].
Right, but "path" in this case is not file path but an ambiguous path. Relative imports work for modules stored in file systems, files (e.g., zip files), databases, etc.
Now, I tried the first of those lines in Python 2.5 and I was surpised that having two files foo and goo, goo importing foo via the first example above, didn't work. What is even worse is that over a year ago I was working on an import semantic for relative imports that would have made the above do as I would have expected.
This leads me to believe that *something* about relative imports is broken, but being that I mostly skipped the earlier portions of this particular thread, I'm not certain what it is. I would *guess* that it has to do with the way the current importer comes up with package relative imports, and I believe it could be fixed by switching to a path-relative import.
That is, when module goo is performing 'from . import foo', you don't look at goo.__name__ to determine where to look for foo, you look at goo.__file__ .
But what about modules stored in a sqlite3 database? How is that supposed to work? What made basing relative imports off of __name__ so nice is that it allowed the import machinery figure out what the resulting absolute module name was. That allowed the modules to be stored any way that you wanted without making any assumptions about how the modules are stored or their location is determined by an importer's find_module method.
With that change in semantic, both of the above cases work just fine, including 'from ..bar import baz', even without the current module being part of a package. That is, running goo.py in the following tree would succeed with the above two imports...
.../ torun/ #include __init__.py if you want this to be a package goo.py foo.py bar/ __init__.py baz.py #I don't know if it would make sense to require __init__.py here
It is still possible to handle import hooks, as the relative import stuff is only really applicable to getting the base path from which to start searching for sub packages (after you have stripped off all leading periods).
But it isn't a file path, it's an absolute module name that you are after.
It also naturally leads to a __name__ semantic that Guido had suggested to me when I was talking about relative imports:
goo.__name__ == '__main__' foo.__name__ == '__main__.foo' baz.__name__ == '__main__..bar.baz'
Which could more or less be used with the current importer; it just needs a special-casing of 'from . import ...' in the __main__ module.
And I am trying to avoid special-casing for this. -Brett