真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Python學(xué)習(xí):import的正確用法

import語(yǔ)句用來(lái)導(dǎo)入其他python文件(稱為模塊module),使用該模塊里定義的類、方法或者變量,從而達(dá)到代碼復(fù)用的目的。

“只有客戶發(fā)展了,才有我們的生存與發(fā)展!”這是創(chuàng)新互聯(lián)的服務(wù)宗旨!把網(wǎng)站當(dāng)作互聯(lián)網(wǎng)產(chǎn)品,產(chǎn)品思維更注重全局思維、需求分析和迭代思維,在網(wǎng)站建設(shè)中就是為了建設(shè)一個(gè)不僅審美在線,而且實(shí)用性極高的網(wǎng)站。創(chuàng)新互聯(lián)對(duì)成都網(wǎng)站制作、做網(wǎng)站、網(wǎng)站制作、網(wǎng)站開(kāi)發(fā)、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站優(yōu)化、網(wǎng)絡(luò)推廣、探索永無(wú)止境。

將要建立文件的結(jié)構(gòu)為:

Tree
|____ m1.py
|____ m2.py
|____ Branch
     |____m3.py
     |____m4.py

首先,先建立一個(gè)文件夾Tree作為工作目錄,并在其內(nèi)建立兩個(gè)文件m1.py和m2.py,在m1.py寫入代碼:

import os
import m2
m2.printSelf()

在m2.py寫入代碼:

def printSelf():
	print('In m2')

打開(kāi)命令行,進(jìn)入到Tree目錄下,敲下python m1.py運(yùn)行,發(fā)現(xiàn)沒(méi)有報(bào)錯(cuò),且打印出In m2,說(shuō)明這樣使用import沒(méi)有問(wèn)題。由此我們總結(jié)出import語(yǔ)句的第一種用法。

  • import module_name。即import后直接接模塊名。在這種情況下,Python會(huì)在兩個(gè)地方尋找這個(gè)模塊,第一是sys.path(通過(guò)運(yùn)行代碼import sys; print(sys.path)查看),os這個(gè)模塊所在的目錄就在列表sys.path中,一般安裝的Python庫(kù)的目錄都可以在sys.path中找到(前提是要將Python的安裝目錄添加到電腦的環(huán)境變量),所以對(duì)于安裝好的庫(kù),我們直接import即可。第二個(gè)地方就是運(yùn)行文件(這里是m1.py)所在的目錄,因?yàn)閙2.py和運(yùn)行文件在同一目錄下,所以上述寫法沒(méi)有問(wèn)題。

用上述方法導(dǎo)入原有的sys.path中的庫(kù)沒(méi)有問(wèn)題。但是,最好不要用上述方法導(dǎo)入同目錄下的文件!因?yàn)檫@可能會(huì)出錯(cuò)。演示這個(gè)錯(cuò)誤需要用到import語(yǔ)句的第二種寫法,所以先來(lái)學(xué)一學(xué)import的第二種寫法。在Tree目錄下新建一個(gè)目錄Branch,在Branch中新建文件m3.py,m3.py的內(nèi)容如下:

def printSelf():
	print('In m3')

如何在m1中導(dǎo)入m3.py呢,請(qǐng)看更改后的m1.py:

from Branch import m3
m3.printSelf()

總結(jié)import語(yǔ)句的第二種用法:

  • from package_name import module_name。一般把模塊組成的集合稱為包(package)。與第一種寫法類似,Python會(huì)在sys.path和運(yùn)行文件目錄這兩個(gè)地方尋找包,然后導(dǎo)入包中名為module_name的模塊。

現(xiàn)在我們來(lái)說(shuō)明為什么不要用import的第一種寫法來(lái)導(dǎo)入同目錄下的文件。在Branch目錄下新建m4.py文件,m4.py的內(nèi)容如下:

def printSelf():
	print('In m4')

然后我們?cè)趍3.py中直接導(dǎo)入m4,m3.py變?yōu)椋?/p>

import m4
def printSelf():
	print('In m3')

這時(shí)候運(yùn)行m1.py就會(huì)報(bào)錯(cuò)了,說(shuō)沒(méi)法導(dǎo)入m4模塊。為什么呢?我們來(lái)看一下導(dǎo)入流程:m1使用from Branch import m3導(dǎo)入m3,然后在m3.py中用import m4導(dǎo)入m4??闯鰡?wèn)題了嗎?m4.py和m1.py不在同一目錄,怎么能直接使用import m4導(dǎo)入m4呢。(可以試試直接在Tree目錄下新建另一個(gè)m4.py文件,你會(huì)發(fā)現(xiàn)再運(yùn)行m1.py就不會(huì)出錯(cuò)了,只不過(guò)導(dǎo)入的是第二個(gè)m4.py了)

面對(duì)上面的錯(cuò)誤,使用python2運(yùn)行m1.py就不會(huì)報(bào)錯(cuò),因?yàn)樵趐ython2中,上面提到的import的兩種寫法都屬于相對(duì)導(dǎo)入,而在python3中,卻屬于絕對(duì)導(dǎo)入。話說(shuō)到了這里,就要牽扯到import中最關(guān)鍵的部分了——相對(duì)導(dǎo)入和絕對(duì)導(dǎo)入。

我們還是談?wù)損ython3的import用法。上面提到的兩種寫法屬于絕對(duì)導(dǎo)入,即用于導(dǎo)入sys.path中的包和運(yùn)行文件所在目錄下的包。對(duì)于sys.path中的包,這種寫法毫無(wú)問(wèn)題;導(dǎo)入自己寫的文件,如果是非運(yùn)行入口文件(上面的m1.py是運(yùn)行入口文件,可以使用絕對(duì)導(dǎo)入),則需要相對(duì)導(dǎo)入。

比如對(duì)于非運(yùn)行入口文件m3.py,其導(dǎo)入m4.py需要使用相對(duì)導(dǎo)入:

from . import m4
def printSelf():
	print('In m3')

這時(shí)候再運(yùn)行m1.py就ok了。列舉一下相對(duì)導(dǎo)入的寫法:

  • from . import module_name。導(dǎo)入和自己同目錄下的模塊。
  • from .package_name import module_name。導(dǎo)入和自己同目錄的包的模塊。
  • from .. import module_name。導(dǎo)入上級(jí)目錄的模塊。
  • from ..package_name import module_name。導(dǎo)入位于上級(jí)目錄下的包的模塊。
  • 當(dāng)然還可以有更多的.,每多一個(gè)點(diǎn)就多往上一層目錄。

不知道你有沒(méi)有留神上面的一句話——“上面的m1.py是運(yùn)行入口文件,可以使用絕對(duì)導(dǎo)入”,這句話是沒(méi)問(wèn)題的,也和我平時(shí)的做法一致。那么,運(yùn)行入口文件可不可以使用相對(duì)導(dǎo)入呢?比如m1.py內(nèi)容改成:

from .Branch import m3
m3.printSelf()

答案是可以,但不能用python m1.py命令,而是需要進(jìn)入到Tree所在的目錄,使用python -m Tree.m1來(lái)運(yùn)行。為什么?關(guān)于前者,PEP 328提案中的一段文字好像給出了原因:

Relative imports use a module's _name_ attribute to determine that
module's position in the package hierarchy. If the module's name does
not contain any package information (e.g. it is set to '__main__')
then relative imports are resolved as if the module were a top level
module, regardless of where the module is actually located on the file
system.

我們應(yīng)該見(jiàn)過(guò)下面一段代碼:

if __name__ == '__main__':
	main()

意思是如果運(yùn)行了當(dāng)前文件,則__name__變量會(huì)置為__main__,然后會(huì)執(zhí)行main函數(shù),如果當(dāng)前文件是被其他文件作為模塊導(dǎo)入的話,則__name__為模塊名,不等于__main__,就不會(huì)執(zhí)行main函數(shù)。比如對(duì)于上述更改后的m1.py,執(zhí)行python m1.py命令后,會(huì)報(bào)如下錯(cuò)誤:

Traceback (most recent call last): 
File "m1.py", line 1, in from .Branch import m3 ModuleNotFoundError: 
No module named '_main_.Branch'; 
'__main__' is not a package

據(jù)此我猜測(cè)執(zhí)行python m1.py命令后,當(dāng)前目錄所代表的包'.'變成了__main__。

那為什么python -m Tree.m1就可以呢?

執(zhí)行指令中的-m是為了讓Python預(yù)先import你要的package或module給你,然后再執(zhí)行script。

即不把m1.py當(dāng)作運(yùn)行入口文件,而是也把它當(dāng)作被導(dǎo)入的模塊,這就和非運(yùn)行入口文件有一樣的表現(xiàn)了。

注意,在Tree目錄下運(yùn)行python -m m1是不可以的,會(huì)報(bào) ImportError: attempted relative import with no known parent package的錯(cuò)誤。因?yàn)閙1.py中的from .Branch import m3中的. ,解釋器并不知道是哪一個(gè)package。使用python -m Tree.m1,解釋器就知道.對(duì)應(yīng)的是Tree這個(gè)package。

那反過(guò)來(lái),如果m1.py使用絕對(duì)導(dǎo)入(from Branch import m3),能使用python -m m1運(yùn)行嗎?我試了一下,如果當(dāng)前目錄是Tree就可以。如果在其他目錄下運(yùn)行,比如在Tree所在的目錄(使用python -m Tree.m1運(yùn)行),就不可以。這可能還是與絕對(duì)導(dǎo)入相關(guān)。

(之前看到了一個(gè)大型項(xiàng)目,其運(yùn)行入口文件有一大堆的相對(duì)導(dǎo)入,我還傻乎乎地用python直接運(yùn)行它。之后看到他給的樣例運(yùn)行命令是帶了-m參數(shù)的?,F(xiàn)在才恍然大悟。)

理解import的難點(diǎn)差不多就這樣了。

下面說(shuō)一說(shuō)import的其他簡(jiǎn)單但實(shí)用的用法。

  • import moudle_name as alias。有些module_name比較長(zhǎng),之后寫它時(shí)較為麻煩,或者module_name會(huì)出現(xiàn)名字沖突,可以用as來(lái)給它改名,如import numpy as np。
  • from module_name import function_name, variable_name, class_name。上面導(dǎo)入的都是整個(gè)模塊,有時(shí)候我們只想使用模塊中的某些函數(shù)、某些變量、某些類,用這種寫法就可以了。使用逗號(hào)可以導(dǎo)入模塊中的多個(gè)元素。
  • 有時(shí)候?qū)氲脑睾芏?,可以使用反斜杠?lái)?yè)Q行,官方推薦使用括號(hào)。
from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
    LEFT, DISABLED, NORMAL, RIDGE, END	# 反斜杠換行
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
    LEFT, DISABLED, NORMAL, RIDGE, END)	# 括號(hào)換行(推薦)

說(shuō)到這感覺(jué)import的核心已經(jīng)說(shuō)完了。再跟著上面的博客說(shuō)一說(shuō)使用import可能碰到的問(wèn)題吧。

問(wèn)題1描述:ValueError: attempted relative import beyond top-level package。直面問(wèn)題的第一步是去了解熟悉它,最好是能復(fù)現(xiàn)它,將錯(cuò)誤暴露在陽(yáng)光之下。仍然是上面四個(gè)文件,稍作修改,四個(gè)文件如下:

# m1.py
from Branch import m3
m3.printSelf()
# m2.py
def printSelf():
	print('module2')
# m3.py
from .. import m2 # 復(fù)現(xiàn)的關(guān)鍵在這 #
print(__name__)
def printSelf():
	print('In m3')
# m4.py
def printSelf():
	print('In m4')

運(yùn)行python m1.py,就會(huì)出現(xiàn)該問(wèn)題。問(wèn)題何在?我猜測(cè),運(yùn)行m1.py后,m1代表的模塊就是頂層模塊(參見(jiàn)上面PEP 328的引用),而m3.py中嘗試導(dǎo)入的m2模塊所在的包(即Tree目錄代表的包)比m1的層級(jí)更高,所以會(huì)報(bào)出這樣的錯(cuò)誤。怎么解決呢?將m1.py的所有導(dǎo)入改為相對(duì)導(dǎo)入,然后進(jìn)入m1.py的上層目錄,運(yùn)行python -m Tree.m1即可。


文章標(biāo)題:Python學(xué)習(xí):import的正確用法
本文地址:http://weahome.cn/article/dsogeii.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部