[Python] Solving the import problem due to the difference in entry points

When executing from the entry point of the application itself, even if there is no problem in execution When I started each module file as an entry point, I sometimes stumbled on the import statement, so I investigated the solution.

--6/12: Fixed because except in try ~ except statement was catch.

import starts from the directory used as the entry point

As a sample, consider the following directory / file structure.

main.py ...Executable file as an application
|
|--[src] ...Directory for storing modules
    |
    |-- module1.py ... main.Module called from py
    |-- module2.py ... module1.Module called from py

If the entry point as an application is main.py, only the directory containing main.py will be recognized as the python path. Therefore, all the files that make up this application need to be imported starting from the directory where main.py is located. In other words, if you want to use module1.py through module2.py in the above directory structure,

/src/module1.py


# -*- coding: utf-8 -*-

import module2 # ImportError!

Then no

/src/module1.py


# -*- coding: utf-8 -*-

import src.module2 # OK

Must be.

Unable to boot from files inside src directory

This description is fine for operation, but problems occur when writing test code in module1.py.

The test code here is supposed to check the operation of classes and functions in module1.py. Isn't it a fairly common sight to write a simple code that calls a function in the file and press the F5 key to see the behavior of the code you wrote on the spot?

However, if you write ʻimport src.module2, when you start the program with module1.py as the entry point, the srcpart cannot be recognized and an ImportError will occur. This is because the execution directory when starting from module1.py changes to the src directory. There is no directory calledsrc` in the src directory.

In this article, I will introduce three ideas that solve this problem and allow you to start the program from either main.py or module1.py. By the way, all have disadvantages and it is not OK if you do this. We are looking for a smarter way, so please comment.

--How to sys.path.append () in the module file -How to sys.path.append () with \ _ \ _ init \ _ \ _.py --How to catch ImportError and branch

How to sys.path.append () in a module file

This is a solution by writing sys.path.append () in module1.py. I think it's a fairly common method.

/src/module1.py


# -*- coding: utf-8 -*-

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '.'))
import module2

This is to add the directory containing the module1.py file to the python path. By doing this, the src directory will be added to the python path and the error will not occur even if the import statement does not have src. In other words, you only need to import module2.py with ʻimport module2`.

However, this method has the problem that if there are a large number of module files, the above description for each file becomes necessary. Also, sys.path.append () is reflected in all files using module1.py, which pollutes the namespace. (You will be able to create ʻimport module 2` in main.py.)

How to sys.path.append () with \ _ \ _ init \ _ \ _.py

It is a method to place \ _ \ _ init \ _ \ _. Py directly under the src directory and perform sys.path.append () in it. In this case, the directory structure looks like this:

main.py ...Executable file as an application
|
|--[src] ...Directory for storing modules
    |
    |-- __init__.py ... sys.path.append()File to run
    |-- module1.py ... main.Module called from py
    |-- module2.py ... module1.Module called from py

Also, the contents of \ _ \ _ init \ _ \ _. Py are as follows.

/src/__init__.py


# -*- coding: utf-8 -*-

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '.'))

What this is doing is that when you do ʻimport src.module1 in main.py, \ _ \ _ init \ _ \ _. Py is also implicitly imported. Specifically, when executing ʻimport src.module1 from main.py, \ _ \ _ init \ _ \ _. Py is imported first, and then module1.py is imported. I will. for that reason,

  1. When importing \ _ \ _ init \ _ \ _. Py, the above sys.path.append () is executed and the src directory is added to the python path.
  2. module1.py is imported, but since the src directory has already been added to the path, module2.py can be imported by specifying ʻimport module2`.

It will be the operation. This way you can reduce the amount of code because each module in the src directory does not need sys.path.append ().

However, as long as you use sys.path.append (), the namespace pollution issue remains.

How to catch ImportError and branch

It is a method to catch ImportError and change the import destination dynamically without using sys.path.append (). Specifically, the code is as follows.

/src/module1.py


# -*- coding: utf-8 -*-

try:
    import src.module2 # main.If you start from py, this will be executed
except ImportError:
    import module2 # module1.If you start from py, this will be executed

If ʻimport src.module2 fails, ʻimport module2 is executed instead. Normally, the application runs from main.py, so you can see the src directory from the execution directory. Therefore, when starting from main.py, the contents of the try block will be executed without any problem.

On the other hand, if you start module1.py as an entry point, you will get an ImportError because you cannot see the src directory. Therefore, catch ImportError in the except block and change the description of the import destination so that it can be imported successfully.

This technique does not use sys.path.append (), so it does not pollute the namespace.

However, the problem of having to add the above description to each module file remains.

Summary

In this article, I've shown you three ways you can start a program from either main.py or module1.py.

--How to sys.path.append () in the module file -How to sys.path.append () with \ _ \ _ init \ _ \ _.py --How to catch ImportError and branch

However, there are disadvantages to each method, so I wonder if it is necessary to use them properly according to the environment.

Recommended Posts

[Python] Solving the import problem due to the difference in entry points
Difference in object ID due to import in Python
In the python command python points to python3.8
Find the difference in Python
python chrome driver ver. Solving the problem of difference
[Python] How to import the library
The 15th offline real-time how to write reference problem in Python
The 14th offline real-time how to write reference problem in python
The 18th offline real-time how to write reference problem in Python
Solve the maximum subarray problem in Python
The 17th offline real-time how to write reference problem implemented in Python
How to get the date and time difference in seconds with python
The file name was bad in Python and I was addicted to import
How to use the C library in Python
Try to calculate a statistical problem in Python
Try to solve the Python class inheritance problem
Summary of how to import files in Python 3
The first step in the constraint satisfaction problem in Python
To dynamically replace the next method in python
About the difference between "==" and "is" in python
Draw graphs in Julia ... Leave the graphs to Python
The 18th offline real-time writing problem in Python
The trick to write flatten concisely in python
How to get the files in the [Python] folder
Solving the equation of motion in Python (odeint)
The 19th offline real-time writing problem in Python
Solving the Python knapsack problem with the greedy algorithm
I want to display the progress in Python!
A solution to the problem that the Python version in Conda cannot be changed
I tried to graph the packages installed in Python
How to get the variable name itself in python
Basic information Write the 2018 fall algorithm problem in Python
How to get the number of digits in Python
[Python] Try to read the cool answer to the FizzBuzz problem
How to know the current directory in Python in Blender
Try to solve the internship assignment problem with Python
The first algorithm to learn with Python: FizzBuzz problem
[Reintroduction to python] How to import via the parent directory
Convert the image in .zip to PDF with Python
I just want to find the 95% confidence interval for the difference in population ratios in Python
I want to write in Python! (3) Utilize the mock
How to use the model learned in Lobe in Python
I tried to solve the problem with Python Vol.1
[Python] How to output the list values in order
To do the equivalent of Ruby's ObjectSpace._id2ref in Python
I want to use the R dataset in python
Python OpenCV tried to display the image in text.
2015-12-26 python2> datetime> Implementation to take the difference in seconds from two ISO format datetime strings> Use .seconds ()
[Python] When you want to import and use your own package in the upper directory
[python] How to check if the Key exists in the dictionary
Output "Draw ferns programmatically" to the drawing process in Python
How to debug the Python standard library in Visual Studio
How to import Python library set up in EFS to Lambda
How to use the __call__ method in a Python class
Change the standard output destination to a file in Python
How to import a file anywhere you like in Python
Various ways to calculate the similarity between data in python
[Note] Import of a file in the parent directory in Python
How to get the last (last) value in a list in Python
Get the current date and time in Python, considering the time difference
I tried to implement the mail sending function in Python