Python 模塊


概念:

對於一個復雜的功能,為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的文件里,這樣,每個文件包含的代碼就相對較少,很多編程語言都采用這種組織代碼的方式。

在Python中,一個.py文件就稱之為一個模塊(Module)。即一個文件被看作一個獨立的模塊,一個模塊也可以被看做是一個文件

使用模塊可以避免函數名和變量名沖突。相同名字的函數和變量完全可以分別存在不同的模塊中,因此,我們自己在編寫模塊時,不必考慮名字會與其他模塊沖突。但是也要注意,盡量不要與內置函數名字沖突。 

 

模塊分為三種:

  • 內置模塊:如sys, os, subprocess, time, json 等等
  • 自定義模塊:自定義模塊時要注意命名,不能和Python自帶的模塊名稱沖突。例如,系統自帶了sys模塊,自己的模塊就不可命名為sys.py,否則將無法導入系統自帶的sys模塊。
  • 開源模塊:公開的第三方模塊, 如 https://pypi.python.org/pypi 。可以使用pip install 安裝,類似於yum 安裝軟件

>>> help('modules')

查看python所有的modules

 

一個Python程序通常包括一個頂層程序文件和其它的模塊文件
頂層文件:包含了程序的主要控制流程
模塊文件:為頂層文件或其他模塊提供各種功能性組件
模塊首次導入import(或重載reload)時,Python會立即執行模塊文件的頂層程序代碼(不在函數內的代碼),而位於函數主體內的代碼直到函數被調用后才會執行

 

導入模塊

Python允許“導入”其它模塊以實現代碼重用,從而也實現了將獨立的代碼文件組織成更大的程序系統。模塊是被導入的,但模塊也可以導入和使用其他模塊,這些模塊可以用Python或其他編程語言寫成

在導入模塊時只能使用模塊名,而不是使用帶.py后綴的模塊文件名

1. import 語句, 用於導入整個模塊

import module1, module2....  # 建議一個import語句只導入一個模塊
import module as module_alias  # 別名(也就是自定義的模塊名稱空間)

>>> import sys,os

>>> import random as rd

 

2. from-import 語句 , 常用於只導入指定模塊的部分屬性或模糊導入
from module import name1,name2....

from pack1.pack2 import *
>>> from random import choice,random,seed

 

import和from import是賦值語句
import和from可執行語句,類似於def,因此,它們可以嵌套在if測試中,出現於def中等等
Python執行到這些語句時才會對其進行解析,這意味着,所有來自模塊的屬性僅在import語句執行后才能使用

 

import的工作機制
import語句導入指定的模塊時會執行3個步驟
1. 找到模塊文件:在模塊搜索路徑下搜索模塊文件
  程序的主目錄
  PYTHONPATH目錄
  標准鏈接庫目錄

2.編譯成字節碼:文件導入時會編譯,因此,頂層文件的.pyc字節碼文件在內部使用后會被丟棄,只有被導入的文件才會留下.pyc文件
3.執行模塊的代碼來創建其所定義的對象:模塊文件中的所有語句從頭至尾依次執行,而此步驟中任何對變量名的賦值運算,都會產生所得到的模塊文件的屬性
注意:模塊只在第一次導入時才會執行如上步驟,后續的導入操作只不過是提取內存中已加載的模塊對象,reload()可用於重新加載模塊

 

包: 用於將一組模塊歸並到一個目錄中,此目錄即為包,目錄名即為包名

包是一個有層次的文件目錄結構,它定義了一個由模塊和子包組成的Python應用執行環境

基於包,Python在執行模塊導入時可以指定模塊的導入路徑 import pack1.pack2.mod1

每個包內都必須有__init__.py文件, __init__.py 可包含python代碼,但通常為空,僅用於扮演包初始化、替目錄產生模塊命名空間以及使用目錄導入時實現from*行為的角色

 

假設有程序結構及依賴關系如下:

web/

├── __init__.py
├── backend

│   ├── __init__.py
│   ├── config

│   │   ├── __init__.py
│   │   └── settings.py  
│   ├── db

│   │   ├── __init__.py
│   │   ├── authentic.py
│   │   └── sqlapi.py  # 需要導入settings和authentic模塊
│   └── logic

│   │   ├── __init__.py
│   │   └── handle.py  # 需要導入 sqlapi 模塊中的select 函數
├── frontend
└── main.py   #需要導入handle模塊

#!/usr/bin/env python
''' main module '''
import sys
from backend.logic import handle
print(sys.path) # 交互模式下可以直接sys.path,在交互模式下打印有所不同

#!/usr/bin/env python
''' handle module '''
from backend.db.sqlapi import select

#!/usr/bin/env python
''' sqlapi module '''
from backend.config import settings
from backend.db import authentic

main.py 執行結果:
['/root/scripts/python/web', '/root/.pyenv/versions/3.6.1/lib/python36.zip', '/root/.pyenv/versions/3.6.1/lib/python3.6', '/root/.pyenv/versions/3.6.1/lib/python3.6/lib-dynload', '/root/.pyenv/versions/3.6.1/lib/python3.6/site-packages']
/root/scripts/python/web 程序主目錄
#/root/.pyenv/versions/3.6.1/
* PYTHONPATH目錄 和 標准鏈接庫目錄,site-packages 存放第三方開源模塊
注意:如果直接執行sqlapi.py 會拋出異常 ModuleNotFoundError: No module named 'backend' 。因為sqlapi模塊所在路徑下並沒有backend目錄,所以找不到路徑,而我們執行main.py之所以可以正常導入,因為backend目錄處於main所在的路徑下。
但我們在編寫一個模塊時往往需要單獨調試,此時我們可以把需要導入模塊的正確路徑添加到sys.path

修改sqlapi.py 如下:
#!/usr/bin/env python
''' sqlapi module '''
import
os,sys basedir=os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.append(basedir) print(sys.path)
from backend.config import settings
from backend.db import authentic
執行結果: [
'/root/scripts/python/web/backend/db', '/root/.pyenv/versions/3.6.1/lib/python36.zip', '/root/.pyenv/versions/3.6.1/lib/python3.6', '/root/.pyenv/versions/3.6.1/lib/python3.6/lib-dynload', '/root/.pyenv/versions/3.6.1/lib/python3.6/site-packages', '/root/scripts/python/web']

也可以使用相對路徑:

#!/usr/bin/env python
''' sqlapi module '''

 import os,sys

  sys.path.append('..')  # .. 表示上一級目錄

  print(sys.path)
  from config import settings
  from db import authentic


執行結果:
['/root/scripts/python/web/backend/db', '/root/.pyenv/versions/3.6.1/lib/python36.zip', '/root/.pyenv/versions/3.6.1/lib/python3.6', '/root/.pyenv/versions/3.6.1/lib/python3.6/lib-dynload', '/root/.pyenv/versions/3.6.1/lib/python3.6/site-packages', '..']

內置變量 __file__:表示當前的文件名

os.path.abspath(path) :返回path的絕對路徑  

os.path.dirname(path) :返回path的目錄(去掉最后一級目錄或文件)

 

一個模塊文件可以直接執行或被導入

每個模塊都有一個名為__name__的內置變量,此變量值會根據調用此模塊的方式發生變化:
1. 如果此文件被作為模塊導入,則__name__的值為模塊名稱
2. 如果此文件被直接執行,則__name__的值為“__main__”

我們在創建模塊時,在尾部添加如下代碼進行模塊的自我測試
if __name__ == '__main__':

  ...

如果模塊被導入,則 if 后的語句就不會執行

 

第三方模塊

官方文檔:https://docs.python.org/3/installing/#

安裝第三方模塊有兩種方式:

1. 通過包管理工具pip完成的

如果你正在使用Mac或Linux,安裝pip本身這個步驟就可以跳過

如果使用Windows,確保安裝時勾選了pipAdd python.exe to Path

注意:Mac或Linux上有可能並存Python 3.x和Python 2.x,因此對應的pip命令是pip3

2. 下載源碼=> 解壓源碼=> 進入目錄=> 編譯源碼:python setup.py build => 安裝源碼: python setup.py install  

在使用源碼安裝時,需要使用到gcc編譯 #yum install gcc

 

以 paramiko模塊為例

paramiko是一個用於做遠程控制的模塊,使用該模塊可以對遠程服務器進行命令或文件操作,fabric和ansible內部的遠程管理就是使用的paramiko來現實。

# python -m pip install paramiko

No package 'libffi' found

# yum install -y libffi-devel

 

導入和使用模塊

#!/usr/bin/env python
''' 通過用戶名和密碼連接服務器 '''
import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('10.104.229.168', 22, 'root', 'password') stdin,stdout,stderr = ssh.exec_command('ifconfig') print(stdout.read()) ssh.close();

執行結果:
b'eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500\n        inet 10.104.229.168  netmask 255.255.192.0  broadcast 10.104.255.255\n        ether 52:54:00:e3:90:ac  txqueuelen 1000  (Ethernet)\n        RX packets 12475918  bytes 2316344006 (2.1 GiB)\n        RX errors 0  dropped 0  overruns 0  frame 0\n        TX packets 12179205  bytes 1357889151 (1.2 GiB)\n        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536\n        inet 127.0.0.1  netmask 255.0.0.0\n        loop  txqueuelen 0  (Local Loopback)\n        RX packets 68  bytes 5552 (5.4 KiB)\n        RX errors 0  dropped 0  overruns 0  frame 0\n        TX packets 68  bytes 5552 (5.4 KiB)\n        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0\n\n'

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM