(C) the use of Python modules and packages

1 Introduction

In order to efficiently use Python Python modules and packages in the project, we need to further understand how they are defined in the project in Python, use and work.

2 Python modules and packages

Basic use front Python modules and packages has been mentioned, is now summarized as follows:

1. First Python import module, then the module can use the functions defined in the class, a defined amount, and other variables. Specific methods are as follows:

import my_module

my_module.do_something()
print(my_module.variable)

2. The first import package module, then the module can use the functions defined in the class, a defined amount, and other variables. Specific methods are as follows:

import my_package_my_module

my_package_my_module.do_something()

Of course, there are other alternative method of introducing the modules, and can make the code look cleaner, as follows:

from my_package import my_module

my_module.do_something()

The method of introducing Python modules are varied, we will introduce more modules in the subsequent introduction method selected for use in different occasions.

3 nested package

Like folder contains folders can continue the same, Python package which can continue to create a Python package.

For example, the package which contains the name of another named my_package my_sub_package packet structure as shown below:

According to this logic, you can nest inside the package bag many layers, which is allowed in the Python syntax. However, considering the practical level, too many levels of nested packages is not a very friendly approach.

At the same time it is undeniable that the tree structure of nested levels of packages greatly help us organize large, complex projects, the logical structure among the various parts of a clear demonstration project, as shown below:

4 module initialization

We know that when the module is imported, the contents of all the definitions contained therein can be called user. This is because, Python code is transferred to all the module while the module will be compiled to run.

With a detailed example of how it works, a creation module named test and typing the following code:

def ta():
    print("test a")

def tb():
    print("test b")

my_var = 0

print("importing test module") 

Open Python interpreter terminal and import module test, command line displays visible importing test module, which proves Python module while introducing all codes contained in the module was compiled to run.

Based on Python this feature, we can put initialization code module is placed directly inside the module. Thus, a module may automatically complete the initialization operation of the module while being introduced.

It is noted that, when multiple modules are required into the same module, in fact, as long as one module import operation, the remaining modules using the module can be defined in the content.

The same principle is based on the above characteristics Python, which also makes the need for multiple identical modules introduced in the above case, to simplify the code.

5 initialization function

The aforementioned initialization method generally initialized implicitly (implicit initialization), characterized by the initialization code distributed among the modules.

Correspondingly, all encapsulated in the initialization code () method is the init an initialization function, called explicit initialization (explicit initialization).

Implicit initialization can not be expressed clearly whether the module has been initialized and the specific contents of the initialization, and then explicitly initialized just to avoid this drawback.

Thus, in the Python programming it encourages users to explicitly initialized preferentially used method to improve the readability of the code.

Examples described in detail, in the test modules defined earlier, we can initialize the contents of the package statement my_var = 0 in the initialization function in the module, as follows:

def init ():
    global   my_v is 
   my_v is = 0

While this may seem redundant, but this can be explicitly initialized, of course, this will require you to call test.init () before using the main module in the project to complete the initialization.

Moreover, explicit initialization method can also control a plurality of modules of the initialization sequence, in order to avoid possible conflicts and implement a specific initialization sequence requirements.

6 package initialization

We know that the initialization packet is encapsulated by a special initialization code _init_.py source file in the package, as shown below:

Python while introducing a package or a module package, the initialization code of the source file is compiled to run.

You may doubt that the package need to initialize the module has been implemented inside the module, why do we need to do initialization packet?

The answer is in the initialization file package _init_.py packet-level user can be accessed directly, for example, you define the following code in _init_.py file:

def say_hello():
    print("hello")

Well, you can directly call the function by the method shown in the following main projects:

import my_packgae
my_package.say_hello()

Unlike the functions defined in the module, you need to call this function in a module, greatly facilitate the users. However, in terms of the Python programming habits, add the code to the package initialization file to achieve is not a good practice.

Because when users browse your source code you want to put code in various functional modules, user-friendly read. At the same time, only one package initialization file, when you put a lot of code are added to the file, will make organizing your code becomes very difficult.

In this regard, there is a method to solve, i.e., the defined code modules in a bag, and then re-introduced into the code in the initialization file, as follows:

from test_package.test_module import say_hello

This will not only meet the code implementation in a module, the package can direct a call to the function. This is a very useful skill, especially when your bag is very complex, which can make you easier access to your defined functions, and so on.

These import import declaration also allows the user to know which defined functions and classes need to use your package, equivalent to some extent, a function, a list of references and index classes.

In summary, when you need to put the code in the initialization file, it is preferable to package the source code in the module, and then introduced into the code mode with the initialization file to achieve.

7 import Import principle and mode

7.1 import Import principle

When we create global variables or functions in Python, Python interpreter the name of a variable or function will be added to the so-called namespace.

For example, when you enter the line print ( "globals ()") in the command, the terminal will display the names of all global variables and functions currently defined in the form of a dictionary.

Indeed, the use of import in Python that is appropriate to add a function module or modules to the namespace the user to be able to use.

7.2 import import mode

So far, we have introduced the following two import use:

  • import <something>
  • from <somewhere> import <something>

The first method does not import restrictions on the number of modules once introduced, Python allows you to import a plurality of modules by such a method, as follows:

import string, datetime, random, math

Likewise, you may be introduced into a plurality of modules or functions from the package or module, as follows:

from math import pi, radians, sin

When the import function module or the need to change the number of rows are large, the operation may be carried out as follows:

from math pi, radians, sin, cos, \
          tan, hypot, asin, acos, atan, atan2

Or by the following operation:

from math import (pi, radians, sin, cos, 
                  tan, hypot, asin, acos, atan, atan2)

While introducing a function module or modules may also change the name of a function, or as follows:

import math as math_ops

At this point math modules will be added as math_ops own name to the global namespace and user calls.

Import module or modules or function also change the name of the function has the following advantages:

  1. Lengthy simplified module or function name;
  2. To avoid naming conflicts, as shown below.
from package1 import utils as utils1
from package2 import utils as utils2

Of course, the second method of introducing the module or function name can also be changed, as follows:

from reports import customers as customer_report
from database import customers as customer_data

Finally, the use of wildcards can define the content import module or package introduced all at once, as follows:

from math import *

This will define the entire contents of math modules are added to the global namespace, if you are importing a package, this package will define the content of all _init_.py file are imported.

By default, the module or package does not come introduced begin underscore wildcard can be introduced into the method will ensure that this requirement is not private variable is introduced in.

When introducing a complex tree structure package introduced previously described methods will become difficult to use. Here are another method for introducing a relative --- introducing method (relative import),

For example, when we need to import the above figure slider.py, by the method described previously as follows:

from program.gui.widgets.editor import slider

Although this can correct import slider, but transferred to the process is very complicated. Thus, the relative introduction method has sent the handy.

当一个模块需要导入位于同一包中的另一个模块时,如下图中utils需要导入slider,可用如下所示语句实现:

 from . import slider 

符号"."表示utils模块所在包位置,并用此符号代替包的名称。

类似地,如下图中位于widgets中的controls模块需要导入位于其子包中的slider模块时,可用如下方法:

 from .editor import slider

上面语句告知Python在当前位置寻找一个名为editor的包,并从此包中导入名为slider的模块。

相反地,若如下图所示位于子包editor中的slider模块需要导入位于widgets包中的controls模块,则实现语句如下:

from .. import controls

一个“.”符号代表当前位置,两个“..”符号代表从当前位置向上升一级包,即当前包的父包。

以此类推,你可以用三个“...”符号实现从当前位置向上升两级包,即当前包的父包的父包……

当然,你也可以将上述方法进行组合使用以实现访问不同层级的包,如下例所示:

from ...dialogs.errors import errDialog

运用相对导入法(relative import)的好处有如下:

  1. 简化导入声明(import statement)并提高其可读性;
  2. 当别人在你写的包中互相引用各模块时,无需知晓包的位置即可实现对模块的引用。

7.3 自定义导入内容

前面提到在默认条件下,模块或包中以下划线开头的将不会被通配符导入方法导入进来,这就使得私有变量不会被导入进来。

那么,当你想更改这一规定以能够不加限制的导入任何变量,又如何做呢?

引入一个名为_all_.的Python专有变量,下面介绍此变量的工作原理:

A = 1
B = 2
C = 3
_all_ = ["A", "B"]

当导入这个模块后,你会发现仅有变量A和B被导入,尽管模块中还定义有变量C,而变量C被忽略则是因为它未被包含进_all_ 列表里面。

类似地,当导入包时,可以在包中_init_.py文件里的_all_ 列表包含需要导入的模块和子包名称,如下所示:

_all_ = ["module1", "module2", "sub-package"]

这时,当你导入此包后,你会发现只有模块module1和module2以及子包sub-package被自动导入。

当你在没有自定义_all_变量情况下,你可以通过查看此变量列表中包含的元素来了解导入模块或包中哪些部分代码是可以被外部使用的。

7.4 循环依赖

当你处理多个模块时,你可能会面临如下所示情形,常称为循环依赖(CIrcular Dependencies)。

# module_1.py

from module_2 import fun2

def funl(items):
    ...
...

# module_2.py

from module_1 import fun1

def fun2(items):
    ...
...

上面示例表明,模块1与模块2相互导入了有关定义内容,如果你尝试运行同时包含有这两个模块的项目时,你会发现无论是在模块1被导入还是在模块2被导入时,都会出现下面错误提示:

ImportError: cannot import name fun1(fun2)

循环依赖现象意味着你的代码设计出现了问题,必须重新构建代码模块结构,以避免此现象的出现,如新创建第三个模块等。

7.5 命令行中运行模块

前面提到,在Python主项目中通常有如下所示结构:

def main():
    ...

if _name_ == "_main_":
    main()

当用户运行项目时,Python解释器便会自动将全局变量_name_的值设为"_main_",故在此结构下,运行项目即会执行main()函数。

下面一个例子来说明其工作原理,定义一个模块test,如下所示:

def double(n):
    return n * 2

if __name__ == "__main__":
    print("double(3) = ", double(3))

当你运行test模块后,你会发现解释器会显示double(3)=6,即验证了上述工作原理的正确性。

此外,用户还可利用此特点直接在命令行中调用以实现模块的某些定义功能,例如定义一个名为funkycase.py的模块,并敲入如下代码:

def funky_case(s):
    letters = []
    capitalize = False
    for letter in s:
        if capitalize:
            letters.append(letter.upper())
        else:
            letters.append(letter.lower())
        capitalize = not capitalize
    return "".join(letters)

上面定义代码实现将字符串中第2、4.……位字符大写的功能,按前面所述方法,可以对此模块进行调用测试。不过,这里我们介绍一些新的内容。

首先,在上面定义的模块中添加如下代码:

import sys
...
if
__name__ == "__main__": if len(sys.argv) != 2: print("You must supply exactly one string!") else: s = sys.argv[1] print(funky_case(s))

这里,需要简要介绍一下上面代码中的sys.argv[ ],它是一个系统内部定义的列表,第一个元素即sys.argv[0]存储的是代码本身的内容,从其列表第二个元素开始存储的是外部用户输入的参数。

故上面代码实现了获取外部用户输入参数并调用定义函数funky_case()的功能。这二者的结合,不仅使定义的模块如之前所述能够被其他模块和主项目所调用,而且还能够被用户在命令行中作为独立的项目调用运行。

不过这里要注意一点,当你创建一个模块并如上述一样需要在命令行中调用时,如果你在模块里面使用了相对导入方法,则会出现attempted relative import of non-package error的错误。

原因是当模块在命令行中被调用时,模块并不知道自己所在包的所在位置。但是如果你只需要在命令行中运行,并没有参数输入,则可通过如下所示命令来避免这个错误:

python -m funkycase.py

当你有参数需要输入时,你就必须选用其他导入方法替代模块中的相对导入法以避免上述错误的出现。

8 小结

 

未完待续……

本文章属于原创作品,欢迎大家转载分享,禁止修改文章的内容。尊重原创,转载请注明来自:躬耕南阳  https://www.cnblogs.com/yangmi511/

Guess you like

Origin www.cnblogs.com/yangmi511/p/12241624.html