I am writing a QGIS plugin. During early development, I wrote and tested the Qt GUI application independently of QGIS. I made use of absolute imports, and everything worked fine. Then, I had to adapt everything to the quirks of QGIS. I can't explain why and haven't been able to find any supporting documentation, but nonetheless: apparently, QGIS needs or strongly prefers relative imports. The majority of other plugins I've looked at (completely anecdotal of course) have all used a flat plugin directory and relative imports. My team decided to keep the hierarchical structure. The plugin now works in QGIS, with the same hierarchical structure, using relative imports. My goal: I would like to still be able to run the GUI independently of QGIS, as it does not (yet) depend on any aspects of QGIS. With the relative imports, this is completely broken. My project directory has the following hierarchy: . ├── app │ └── main.py ├── __init__.py ├── justfile ├── metadata.txt ├── plugin.py ├── README.md ├── resources │ ├── name_resolver.py │ └── response_codes.py ├── processing │ ├── B_processor.py │ ├── A_processor.py │ ├── processor_core.py │ ├── processor_interface.py │ ├── processor_query_ui.py │ └── processor_query_ui.ui └── tests ├── __init__.py ├── test_A_processor.py └── test_processor_core.py  The app directory and its main.py module are where I'm trying to run the GUI independently of QGIS. The GUI is in processing/processor_query_ui.py. app/main.py is as follows: if __name__ == "__main__": import sys from PyQt5 import QtWidgets from processing.processor_query_ui import UI_DataFinderUI app = QtWidgets.QApplication(sys.argv) ui = UI_DataFinderUI() ui.show() sys.exit(app.exec_())  When running main from the top level, all imports within main.py work: $ python app/main.py  What does NOT work are the subsequent imports: Traceback (most recent call last): File "/path/to/app/main.py", line 4, in <module> from processing.processor_query_ui import UI_DataFinderUI File "/path/to/processing/processor_query_ui.py", line 2, in <module> from .A_processor import Aprocessor File "/path/to/processing/A_processor.py", line 5, in <module> from ..resources.response_codes import RESPONSE_CODES ImportError: attempted relative import beyond top-level package  This shows that all imports in main.py are working correctly. But when processor_query_ui tries to do its imports, those ones fail. I have tried adding __init__.py files to all first level directories as well (e.g. {app,resources,processing}/__init__.py) to no vail. Running python -m app/main{.py} doesn't work, though I didn't really expect it to. For pytest to work, the tests directory must have an init.py file; then, pytest works as either pytest or python -m pytest. My goal is to be able to run the GUI in processing/processor_query_ui.py as a standalone app, by writing some kind of adaptor such that I do not have to change the current directory structure or relative imports (which, as above, make QGIS happy). Any advice is greatly appreciated.
What does your python path look like? For those relative imports to work, you need the directory containing your repository directory (not just the repository directory itself) to be on the python path. The reason the relative imports work when you run the code as a QGIS plugin is that the directory containing your repo —- i.e., the QGIS plugin directory —- is already on the python path in the QGIS python environment. To avoid that issue, I would suggest restructuring your repo as follows, with all of the plugin code in a subdirectory off of the top-level directory (I’d suggest a more descriptive name than ‘plugin’, but I don’t know what your plugin is called). . ├── app │ └── main.py ├── justfile ├── README.md ├── plugin │ ├── __init__.py │ ├── plugin.py │ ├── metadata.txt │ ├── resources │ │ ├── name_resolver.py │ │ └── response_codes.py │ └── processing │ ├── B_processor.py │ ├── A_processor.py │ ├── processor_core.py │ ├── processor_interface.py │ ├── processor_query_ui.py │ └── processor_query_ui.ui └── tests ├── __init__.py ├── test_A_processor.py └── test_processor_core.py  This has a couple of advantages: First, it lets you distribute just the plugin subdirectory as your plugin. Your plugin users don’t need your unit tests or the app directory or the README. Second, if you now add your top level repository directory to the python path (which I assume it already is or your absolute imports wouldn’t work), you should be able to do the absolute imports from outside the plugin folder (you’ll have to change those to import plugin.processing and plugin.resources and their contents instead of just processing etc), and you should then be able to do relative imports within plugin directory. Your tests will also need to use absolute imports if they don’t already. This structure has worked for me for QGIS plugins with multiple levels of submodules/subfolders.