The handling of modules with the same name as packages in Python

  • 2020-05-30 20:34:30
  • OfStack

preface

In programming development, I feel that as long as I follow the specification, there are very few problems. When you first learn a skill, you do encounter a lot of pitfalls. It's good to step into more holes, learn more, and feel more and more important to do according to the norms, which are designed to avoid problems. Sometimes you really should take the advice of experienced people and not go it alone. It seems that this is not the focus of this article, in fact, my focus is to express, as far as possible in accordance with the norms, so that you will not take a lot of detours.

The main programming language I use now is Python. So far, I feel that the pits I step on are still very few and I have not encountered any strange problems. In fact, this is not a good thing, do not step on the pit, a lot of lying in the dark knowledge you will not understand, so it is difficult to grow. Fortunately, there are some colleagues who will step into the pit.

My colleague asked me if in Python, if a module and a package have the same name, you can only import the package, and what should you do if you want to import the module? What he means is something like this: in the same level 1 directory of the project, there is an foo.py file and an foo/ directory. If import foo will import the content of foo/ instead of the content of foo.py.

When asked this question, the first thing I felt was surprise, which was clearly ambiguous. I wouldn't have designed the module name and package name to be exactly the same, because it's essentially impossible to tell who you're importing when you import. Unless the system specifies, for example, that only packages can be imported in this case.

My subconscious thought this should be an error. The Python interpreter doesn't know who to import. However, my colleague told me that someone else's code was written this way, and that in this case the package would be imported by default. That's ok, and the interpreter already states that the package will always be imported in this case.

In order to verify this point, I wrote a simple project. The project structure is as follows:


.
 ├ ─ ─  main.py
 └ ─ ─  same
  ├ ─ ─  api
  │   └ ─ ─  __init__.py
  ├ ─ ─  auth
  │   └ ─ ─  __init__.py
  ├ ─ ─  auth.py
  └ ─ ─  __init__.py

Among them:

Content of same/api/ s31en/s32en__ /py:


from .. import auth

S 38en /auth/ s 40en__. S 41en


auth_str = "This is str in package!"

same/ auth.py


auth_str = "This is str in module!"

main. Contents of py:


from __future__ import print_function

from same.api import auth

# Script starts from here

if __name__ == "__main__":
 print(auth.auth_str)

It's a little bit more complicated, ha, ha, ha, ha, ha, ha, ha, ha, ha, ha, ha, ha. I am in same.auth One is defined in the package auth_str String, again in the same name same.auth A module is defined with the same name auth_str String, then try to import auth in the same.api package, and finally try the output in main.py same.api.auth.auth_str To see which string gets printed. Try main. py with Python2 and Python3 at the same time. The results are as follows:


This is str in package!

Here we verify that our guess is correct and that the interpreter does import only the contents of the package. However, I don't know if there is any official information that this is the case, so I'm not sure, it's just a coincidence.

So, I started looking at the data to verify this conclusion. I will tell you the truth, for a poor English level to you can not imagine me, can only try to use baidu search under the answer. The fact is, using baidu is often a pity. After a while, no result, I have to brave the skin to try English search. The following question was found on stackoverflow:

How python deals with module and package having the same name?

Including one answered Python official document describing the module search path mentioned this point 1: https: / / docs python. org / 3 / tutorial modules. html # the - module search -- path.

The document is described in the following 1 paragraph:

After initialization, Python programs can modify sys.path. The directory containing the script being run is placed at the beginning of the search path, ahead of the standard library path. This means that scripts in that directory will be loaded instead of modules of the same name in the library directory. This is an error unless the replacement is intended. See section Standard Modules for more information.

That is, the directory will be searched first in the library's search path, which means that the directory will be loaded instead of the module with the same name.

This finally relieved, the previous conclusion has been confirmed. In Python, packages are imported if you try to import modules and packages with the same name. In this case, if you want to import a module, you may need to use some 'hack' methods. There are some examples below the stackoverflow post mentioned above. Of course, the best thing to do is to avoid this design, so you won't have to spend so much time looking it up and writing articles like this one.

conclusion


Related articles: