Python modules frustration

I’m trying to turn my lolslackbot code into a proper set of Python modules, so I can manage the code with pip and venv. That means turning my moduleless code into a bunch of packaged modules. And writing setuptools.

And oh god it’s awful. Python’s handling of module namespaces and imports is confusing, particularly when circular dependencies are involved and/or command line scripts as opposed to Python libraries. I can’t even tell if this caveat applies to me or not

Note that relative imports are based on the name of the current module. Since the name of the main module is always “__main__”, modules intended for use as the main module of a Python application must always use absolute imports.

The other problem is years of cruft that’s accumulated in Python packaging tools. setuptools, disttools, easy_install, pip, wheel, egg, virtualenv, pyvenv.. To some extent this has been rationalized in modern Python: use pip and setuptools and call it a day. But the docs that are out there are hard to follow because they tend to describe the history, not the current practice.

The two best documents I’ve found so far:

Right now I’m hung up on some code where “from . import lib” works in some contexts but not others. I think it may be related to circular dependencies but am not sure.

Update: turns out Python doesn’t actually support circular imports, despite looking like it does in many circumstances. So now I’m having to refactor all my code that worked just fine to not have module A import module B which imports module A. I feel like I’m programming in C again, only without #ifndef macros. One partial solution is to only do the imports inside the running function code. That avoids the circular imports at import time, at the expense of deferring the import code machinery running in your actual execution path all the time. Maybe I’m misunderstanding how to really make this work. (There’s a bunch of arrogant advice which says “if your code has circular imports you should refactor it.” No, imports are how you manage namespaces in Python, and Python shouldn’t have this limitation.)