[PYTHON] attempted relative import beyond top-level package and how to resolve when angry

Introduction

I was afraid to use it in UnitTest without thinking about it with relative import of Python, or to dig up a directory, but I thought that I would seriously try to solve it, and I was able to solve it after investigating, so as a record I will leave it.

Try to reproduce the attempted relative import beyond top-level package

With the following directory structure

/package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

moduleZ.py is moduleX.When importing py, that is, moduleZ.In the py file



```python
from ..subpackage1 import moduleX

Write

$ pwd 
/package
$ cd subpackage2
$ python moduleZ.py
ValueError: attempted relative import beyond top-level package

## or
$ python subpackage2/moduleZ.py
ValueError: attempted relative import beyond top-level package

Can be reproduced safely.

To solve

Two solutions here [1] offered a very good solution. So I used it. This time

moduleZ.import py



```python
from subpackage1 import moduleX

Rewrite as

$ pwd
/package
$ python -m subpackage2.moduleZ

Take the method to solve with.

-m runs as a python script as a library module. So/package to root directory(__main__)As subpackage2/moduleZ.Since py is running, subpackage1/moduleX.You can import and execute py.



## Python's way of thinking about import
 Python is [Package concept](https://www.python.org/doc/essays/packages/) [2] is the location where `` `python ~~~ .py``` is executed `` `root It recognizes as ``` and recognizes` `~~~ .py``` that exists under root as a module (` `~~~ .py```). Only one `` `~~~ .py``` script is recognized as this root. Furthermore, when you run the script with ``` python ~~~ .py```, Python's [`` __main__``` is a special case of import](https://docs.python.org/ja/3/ reference / import.html # special-considerations-for-main) [3] forces the module name to be `` `__ main__```. Therefore, the location of the execution directory is important as to which Python script is being executed by root (`` __main__```).
 In this failure example, root (`` __main__```) will be the location of `` `moduleZ.py``` (this time, `` `subpackage2```).

```bash
$ pwd 
/package
$ cd subpackage2
$ python moduleZ.py
## or
python subpackage2/moduleZ.py

As a result, when importing ( `subpackage1```) with relative import, trying to reference ( / pacakge```) above root (`` subpackage2), ValueError : attempted relative import beyond top-level packageand angry, Python script cannot be executed. By the way, REPL starting with python has the current directory as` `__main__, so you can import it by executing it in the root directory. On the contrary, if you execute it in some package (directory), you may not be able to import it.

Finally

I used Python's import with a mysterious feeling that I didn't understand, so I was able to organize it relatively and became attached to it. I think there are many people who use `python -m` in Python UnitTest if it is familiar. If you have any misunderstandings or typos due to insufficient research, I would appreciate it if you could describe them in the comments. Also, if you don't understand Python import honestly in this article, please take a look at the reference materials.

Reference material

[1] Relative imports for the billionth time [2] Built-in Package Support in Python 1.5 [3] 5.8. Special considerations for main

Recommended Posts

attempted relative import beyond top-level package and how to resolve when angry
How to solve "attempted relative import beyond top-level package" when importing in Python
How to package and distribute Python scripts
[Django] How to resolve errors when installing mysqlclient
How to use import
[Python] When you want to import and use your own package in the upper directory
How to resolve variable scope conflicts between Jinja2 and AngularJS
How to resolve CSRF Protection when using AngularJS with Django
How to import CSV and TSV files into SQLite with Python
How to deal with errors when installing whitenoise and deploying to Heroku
How to deal with errors when installing Python and pip with choco
[Introduction to Udemy Python3 + Application] 69. Import of absolute path and relative path
How to resolve the error from toimage (from PIL.Image import fromarray as toimage)