python 无法导入父级以上目录内的module

I’ve almost never been able to write correct Python import statements on the first go. Behavior is inconsistent between Python 2.7 and Python 3.6 (the two versions that I test here), and there is no single method for guaranteeing that imports will always work. This post is my dive into how to resolve common importing problems. Unless otherwise stated, all examples here work with both Python 2.7 and 3.6.

Summary / Key Points

  • import statements search through the list of paths in sys.path
  • sys.path always includes the path of the script invoked on the command line and is agnostic to the working directory on the command line.
  • importing a package is conceptually the same as importing that package’s __init__.py file

Basic Definitions

  • module: any *.py file. Its name is the file name.
  • built-in module: a “module” (written in C) that is compiled into the Python interpreter, and therefore does not have a *.py file.
  • package: any folder containing a file named __init__.py in it. Its name is the name of the folder.
    • in Python 3.3 and above, any folder (even without a __init__.py file) is considered a package
  • object: in Python, almost everything is an object - functions, classes, variables, etc.

Example Directory Structure

test/                      # root folder
    packA/                 # package packA
        subA/              # subpackage subA
            __init__.py
            sa1.py
            sa2.py
        __init__.py
        a1.py
        a2.py
    packB/                 # package packB (implicit namespace package)
        b1.py
        b2.py
    math.py
    random.py
    other.py
    start.py

Note that we do not place a __init__.py file in our root test/ folder.

What is an import?

When a module is imported, Python runs all of the code in the module file. When a package is imported, Python runs all of the code in the package’s __init__.py file, if such a file exists. All of the objects defined in the module or the package’s __init__.py file are made available to the importer.

Basics of the Python import and sys.path

According to Python documentation, here is how an import statement searches for the correct module or package to import:

When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.pathsys.path is initialized from these locations:

  • The directory containing the input script (or the current directory when no file is specified).
  • PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
  • The installation-dependent default.

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.Source: Python 2 and 3

重要内容翻译:  当需要导入spam模块时,解释器首先在内建的模块中搜索。如果没有找到,就会在变量sys.path指向的文件夹列表中搜索,这些文件夹列表在一个list中包含。sys.path初始化时,指向以下文件夹:

  • 当前python脚本所在的文件夹(如果没有指定python脚本,则是当前文件夹)
  • 环境变量PYTHONPATH(文件夹列表,和shell中的环境变量PATH语法相同)
  • 默认的依赖安装

初始化完成之后,可以在程序中修改sys.path  。 当前python脚本所在目录,将会被放在list的开头,然后是标准库的所在目录。 这意味着,如果当前脚本所在的目录如果有和标准库所在目录,如果有相同module的话,自己的module将优先被加载到。

参考下文中的举例:自定义的random.py和系统的random.py的比较。已经用红色字体标注

 

Technically, Python’s documentation is incomplete. The interpreter will not only look for a file (i.e. module) named spam.py, it will also look for a folder (i.e. package) named spam.

Note that the Python interpreter first searches through the list of built-in modules, modules that are compiled directly into the Python interpreter. This list of built-in modules is installation-dependent and can be found in sys.builtin_module_names (Python 2 and 3). Some built-in modules that are commonly included are sys (always included), mathitertools, and time, among others.

Unlike built-in modules which are first in the search path, the rest of the modules in Python’s standard library (not built-ins) come after the directory of the current script. This leads to confusing behavior: it is possible to “replace” some but not all modules in Python’s standard library. For example, on my computer (Windows 10, Python 3.6), the math module is a built-in module, whereas the random module is not. Thus, import math in start.py will import the math module from the standard library, NOT my own math.py file in the same directory. However, import random in start.py will import my random.py file, NOT the random module from the standard library.

Also, Python imports are case-sensitive. import Spam is not the same as import spam.

The function pkgutil.iter_modules (Python 2 and 3) can be used to get a list of all importable modules from a given path:

import pkgutil
search_path = '.' # set to None to see all modules importable from sys.path
all_modules = [x[1] for x in pkgutil.iter_modules(path=search_path)]
print(all_modules)

Sources

  • How to get a list of built-in modules in python?
  • Thank you etene for pointing out the difference between built-in modules and other modules in Python’s standard library (Issue 2)

More on sys.path

To see what is in sys.path, run the following in the interpreter or as a script:

import sys
print(sys.path)

Python’s documentation for sys.path describes it as…

A list of strings that specifies the search path for modules. Initialized from the environment variable PYTHONPATH, plus an installation-dependent default.

As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.

Source: Python 2 and 3

The documentation for Python’s command line interface adds the following about running scripts from the command line. Specifically, when running python

你可能感兴趣的:(Python)