Rob Gaddi <rgaddi@technologyhighland.invalid> writes: > So, I'll take the app I'm working on right now as an example. I've got > 348 lines in my __init__.py, and another 200 in another library. > Little baby program.
By “another library”, I think you mean “another module”. I'll assume that in the rest of this response. > My library code isn't in __init__.py (or previously in __main__) > because I'm trying to dodge recursive imports; it's there because the > code is short enough and tightly-coupled enough that I didn't see > upside in splitting any of it out to a separate file. Sure, there's no need to make more modules if the code is small and coherent. But you describe it as “tightly-coupled”; that's a warning sign already. How do you automate tests of its individual units? The code should be in separate functions with tightly-defined scope and narrow, well-specified interfaces. > Under other circumstances when the app has become substantial, the > bulk of the application code winds up in, e.g. mainwindow.py, and the > __main__ does nothing but call mainwindow.main(). Great! So you already have an entry point for Setuptools: the entry point is something like "fooapp.mainwindow:main". > The advice to reduce the entry point code (be it __init__ or __main__) > to a small stub and move the bulk of the code to another [module] > doesn't change the underlying situation. Setuptools seems to require > that the application be a "package", i.e. a thing that has an > __init__.py. But the python application start mechanism seems to be > steering me to using a __main__. It's not Setuptools per se, it's Python's import mechanism. It is a deliberate design decision that direct import of a module makes that module blind to its location in the package hierarchy. That's a design decision I deplore, because it makes something that should be easy (write a command directly into a file and invoke that file as an executable program) tortuously difficult when the program comprises several modules. > I found a recommendation at https://chriswarrick.com/blog/2014/09/15/ > python-apps-the-right-way-entry_points-and-scripts/ that seems to say > that I should get around this by simply having an empty __init__. More importantly, the core tip there is that you can write your entry point as "fooapp.__main__:main". > I guess I can move the program to foobar.py, have an empty __init__, a > stub __main__ that just calls foobar.main(), and an entry-point of > foobar.foobar:main . It just feels like a bit of a heavy solution to > have two unnecessary files. Well, they're small but not unnecessary. They're explicitly telling Python the meaning of a particular directory, rather than leaving it to guess. The quirks of Python's import system, and especially the implications for trying to just get ‘./fooapp’ working, are covered in a “here's some traps to avoid” article by Nick Coghlan <URL:http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html>. I really wish Python had a better solution for this, but it doesn't. This is one of the few downsides of Python's design IMO, and we just need to work with it. -- \ “I find the whole business of religion profoundly interesting. | `\ But it does mystify me that otherwise intelligent people take | _o__) it seriously.” —Douglas Adams | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list