python import函數,python模塊導入及屬性:import

 2023-12-09 阅读 28 评论 0

摘要:http://blog.csdn.net/pipisorry/article/details/43313197 模塊和包 1. python程序由包(package)、模塊(module)和函數組成。 2. 包是由一系列模塊組成的集合。當不同作的模塊進行按文件夾分類后再組成一個整體的庫,可以稱為包。為了讓Py

http://blog.csdn.net/pipisorry/article/details/43313197

模塊和包

1. python程序由包(package)、模塊(module)和函數組成。

2. 是由一系列模塊組成的集合。當不同作的模塊進行按文件夾分類后再組成一個整體的庫,可以稱為包。為了讓Python將目錄當做內容包,目錄中必須包含__init__.py文件,用于標識當前文件夾是一個包。最簡單的情況下,只需要一個空的__init__.py文件即可。包就是一個完成特定任務的工具箱,包的作用是實現程序的重用。包導入會讓模塊扮演的角色更為明顯,也使代碼更具有可讀性。

python import函數、3. 模塊是處理某一類問題的函數和類的集合,由代碼、函數和類組成。函數是一段可以重復多次調用的代碼。模塊把一組相關的函數或代碼組織到一個文件中,一個文件即是一個模塊。每個模塊文件是一個獨立完備的命名空間,一個模塊文件不能看到其他文件定義的變量名,除非它明確地導入了那個文件,模塊文件起到了最小化命名沖突的作用。

皮皮blog

?

?

python中引入包

兩種導入語句

Python import變量。導入模塊使用import和from語句(都是隱性的賦值語句),以及reload函數。可以導入模塊名,還可以指定目錄路徑(Python代碼的目錄就稱為包),包導入就是把計算機上的目錄變成另一個Python命名空間,包的屬性就是該目錄包含的子目錄和模塊文件。當多個同名程序文件安裝在某機器上時,包導入可以偶爾用來解決導入的不確定性。導入包也使用import和from語句。

import語句

import file_name可以導入當前目錄上file_name.py這個模塊,但是里面的內容,必須通過file_name.func/file_name.var 來訪問。

如果你一直在某個環境,比如解釋器下面,你已經導入過某個模塊 ,現在你對模塊進行了修改,這里你需要用reload(modulename)來重新載入。

Python里,多次import的效果是只有第一次import有用,如果想要重新載入模塊應該用reload(your_module)。

import Python、局部import時還可以使用這種語法

__import__('shutil').rmtree(DATA_DIR)

subpackage導入時要這樣:

__import__('geopy.distance').distance.vincenty(i, j).miles

python print。相當于import geopy.distance; distance.vincenty(i, j).miles?

?from import語句

另外一種導入方式為import func/var from file_name。這樣func/var直接可用,但是file_name是沒有定義的。

從file_name中導入所有:import * from file_name。這樣會導入所有除了以下劃線開頭的命名。實際代碼中這樣做往往是不被鼓勵的。

導入模塊的兩種方式的不同之處

1. 與import類似, 被導入的module仍然會執行且僅執行一次

python常用模塊,2. from *** import 的實質

當以 "from *** import " 方式導入module時, python會在當前module 的命名空間中新建相應的命名.

即, "from t2 import var1" 相當于:

import t2

pythonista?var1= t2.var1

在此過程中有一個隱含的賦值的過程

由于python賦值操作特性(參考python變量名本質),在當前代碼中對"var1"的修改并不能影響到t2.py中"var1"的值。同時,在t2.py中對var1的修改也不能反映到當前的代碼。如果實在要改,可以這樣:import t2; t2.var1 = something

包的兩種導入模塊或模塊內函數的/變量的方式可能出現的錯誤

from package import item  # 這種方式,item可以是包中的一個子模塊或子包,也可以是包中定義的其他命名,像函數、類、變量。
import item.subitem.subsubitem # 這些子項必須是包,最后的子項是包或模塊。但不能為函數、類或變量。否則出錯:No module named ***

Note:?

python怎么用,1. 陷阱:使用from導入變量,而那些變量碰巧和作用域中現有的變量同名,本地變量就會被悄悄地覆蓋掉;使用import則沒這個問題。

2.當b.py文件以from filename import fun方式從a.py文件引入函數fun時,如果有可執行語句在函數fun外,則引入后,執行b.py也會同時執行a.py在函數外的可執行語句,故一般不要把可執行腳本直接寫到函數外,實在不想寫入函數中也可以使用if __name__ == '__main__':...的方式。

皮皮blog

?

?

模塊的搜索路徑

首先會搜索解析器的當前目錄。然后會到sys.path變量中給出的目錄列表中查找。

>>> import sys
>>> sys.path
['', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
  1. 輸入腳 本的目錄(當前目錄)
  2. 環境變量PYTHONPATH表示的目錄列表中搜索
  3. Ptyon的默認安裝路徑中搜索。

Note:sys.path包含輸入模塊的目錄名列表。我們可以觀察到sys.path的第一個字符串是空的——這個空的字符串表示當前目錄也是sys.path的一部分,這與PYTHONPATH環境變量是相同的。這意味著你可以直接輸入位于當前目錄的模塊。否則,你得把你的模塊放在sys.path所列的目錄之一。[python系統模塊sys、os和路徑、系統命令]

皮皮blog

?

?

從 * 導入包和__init__.py 中的__all__ 列表

當用戶寫下 from sound.Effects import * 時會發生什么事?理想中,總是希望在文件系統中找出包中所有的子模塊,然后導入它們。這可能會花掉很有長時間,并且出現期待之外的邊界效應,導出了希望只能顯式導入的包。

對于包的作者來說唯一的解決方案就是給提供一個明確的包索引。

import 語句按如下條件進行轉換:

執行 from package import *時,如果包中的__init__.py 代碼定義了一個名為__all__ 的列表,就會按照列表中給出的模塊名進行導入。新版本的包發布時作者可以任意更新這個列表。如果包作者不想 import * 的時候導入他們的包中所有模塊,那么也可能會決定不支持它( import * )。例如,sounds/effects/__init__.py 這個文件可能包括如下代碼:

__all__ = ["echo", "surround", "reverse"]

這意味著 from Sound.Effects import * 語句會從 sound 包中導入以上三個已命名的子模塊。

如果沒有定義 __all__from Sound.Effects import * 語句 不會 從 sound.effects 包中導入所有的子模塊。無論包中定義多少命名,只能確定的是導入了 sound.effects 包(可能會運行__init__.py 中的初始化代碼)以及包中定義的所有命名會隨之導入。這樣就從__init__.py 中導入了每一個命名(以及明確導入的子模塊)。同樣也包括了前述的 import 語句從包中明確導入的子模塊。

考慮以下代碼:

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

在這個例子中,echo 和 surround 模塊導入了當前的命名空間,這是因為執行 from...import 語句時它們已經定義在 sound.effects 包中了(定義了__all__時也會同樣工作)。

盡管某些模塊設計為使用 import * 時它只導出符全某種模式的命名,仍然不建議在生產代碼中使用這種寫法。

記住,from Package import specific_submodule 沒有錯誤!事實上,除非導入的模塊需要使用其它包中的同名子模塊,否則這是推薦的寫法。

皮皮blog

?

?

包的絕對導入和相對導入

python 2.7及之前版本

中默認是先“相對”后“絕對”的順序搜索模塊,也就是說先在模塊所在同一個包內搜索然后在sys.path中搜索。為此,所有的導入現在都被認為是絕對的, 也就是說這些名字必須通過 Python 路徑(sys.path 或是 PYTHONPATH )來訪問。python 2.x在包內模塊的導入,順序是:
1、當前目錄
2、上一個目錄
3、找不到再往上
4、系統環境變量
5、標準庫
6、前三個在搜索路徑下的 .pth文件

Python 2.7之后版本

包的絕對導入

很多情況下導入子包會導致和真正的標準庫模塊發生(事實上是它們的名字)沖突。 包模塊會把名字相同的標準庫模塊隱藏掉, 因為它首先在包內執行相對導入, 隱藏掉標準庫模塊。

從 Python 2.7 開始默認絕對導入。 python3.x 中的包內的模塊導入原則編程了:如果要相對導入,那么一定是顯式聲明,并且,這個聲明不是告訴python一個模塊查找偏好,而是一種約束(也就是說,一旦聲明,必須是相對導入)

from __future__ import absolute_import: 在 3.0 以前的舊版本中啟用相對導入等特性所必須的 future 語句。

Python3絕對導入:按照sys.path順序搜索,先主目錄(sys.path中第一項''),然后PYTHONPATH環境變量、標準庫路徑、pth指定路徑等。

包的相對導入

import 語句總是絕對導入的, 所以相對導入只應用于 from-import 語句

Python3相對導入:在模塊所在同一個包內搜索,注意該包目錄與主目錄的區別。Python3中,每一個點號代替上一層目錄。這樣做的目的,主要是防止覆蓋命名空間。

Note:從當前目錄相對導入可以省略.號,不過不省略更好,以免之后修改系統不會自動調整(使用pycharm時,移動文件時,有.號它會自動修改導入路徑)。

Example

Phone/

??????? __init__.py
???????common_util.py?????????? #其中包含setup
??????? Fax/
??????? ? ? ? __init__.py
??????? ? ? ? G3.py?????????????????????? #其中包含dial
???????? Mobile/
?? ? ? ? ? ??? __init__.py
???????? ? ? ? Analog.py???????? ? ? ? #其中包含dial
????? ? ? ? ?? Digital.py

在 Mobile.Analog.Digital , 也就是 Digital.py 模塊中, 不能簡單地使用錯誤語法(只能工作在舊版本的 Python 下, 在新的版本中它會導致一個警告, 或者干脆不能工作)
import Analog
from Analog import dial

正確絕對導入方法:

from Phone.Mobile.Analog import dial

正確相對導入方法:
from .Analog import dial??????????? # . 代表當前.py文件所在目錄Mobile/
from ..common_util import setup
from ..Fax import G3.dial.

[Python核心編程2ed]

[Python 相對導入]

相對導入要注意的問題和常見錯誤

lz總結的一個模塊導入法則:Use relative import only in modules and run the scripts outside the package. 也就是說使用相對導入的文件不應該是要運行執行的文件,而應該只是外層調用的模塊。但是如果你非要在packges里面做測試的話,那就不要使用相對導入。Note that relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports.[documentation]

終極解決方案

import sys
import os
#將mymodule模塊(目錄)所在的目錄(如這個py文件的../..)加入到pythonpath中就可以使用from mymodule import *了
sys.path.append(os.path.join(os.path.split(os.path.realpath(__file__))[0],"../..")) 

try:
?from .mymodule import myclass
except Exception: #ImportError
?from mymodule import myclass

示例

Note: 最頂層的SocialNetworks是一個單純的目錄,而下層的SocialNetworks開始就是一個python package.

運行MainTest.py,EBM中導入的就是try中的import

??

直接運行EBM.py,是從except中import的

也就是使用

try:from .mymodule import myclass
except Exception: #ImportErrorfrom mymodule import myclass

來區分包內和包外的運行測試。

[SystemError: Parent module '' not loaded, cannot perform relative import]

后來lz發現pycharm中不用加入路徑就可以導入except中的語句,from SocialNetworks.SocialNetworks引入成功的原因是lz在pycharm中添加了add content roots to pythonpath了,這樣sys.path中多了一個整個項目project的路徑/media/pika/files/mine/python_workspace,里面的目錄就被當成包使用,所以可以引入成功!在代碼中加入路徑后,在pycharm之外也可以正常運行from SocialNetworks.SocialNetworks了,所以lz建議關閉pycharm的add roots to pythonpath這種功能。

[Why does PyCharm always add “contents root” to my PYTHONPATH, and what PYTHONPATH?]

下面這幾個錯誤好像都可以使用上述的方法解決,下面是以前總結的解決方案,不怎么好。

python拓展包的調用

>>> import sys
>>> sys.path
['', '/home/pipi/ENV/ubuntu_env/lib/python35.zip', '/home/pipi/ENV/ubuntu_env/lib/python3.5', '/home/pipi/ENV/ubuntu_env/lib/python3.5/plat-x86_64-linux-gnu', '/home/pipi/ENV/ubuntu_env/lib/python3.5/lib-dynload', '/usr/lib/python3.5', '/usr/lib/python3.5/plat-x86_64-linux-gnu', '/home/pipi/ENV/ubuntu_env/lib/python3.5/site-packages']
可以看到/home/pipi/ENV/ubuntu_env/lib/python3.5/site-packages在sys.path中,所以可以在python中調用這些不同的拓展包(如使用pip安裝的包)。

1.報錯:ValueError: Attempted relative import beyond toplevel packages

案例1:

目錄樹
case1/
├── cat
│ ? ├── __init__.py
│ ? ├── cat.py
├── dog
│ ? ├── __init__.py
│ ? └── dog.py
├── __init__.py
└── main.py
?
代碼
# case1/cat/cat.py
from .. import dog

# case1/main.py
import cat.cat

執行
python case1/main.py

錯誤原因:
這里的 case1 是一個包,但當你直接執行 main.py 的時候,就沒有把完整的 case1 當作一個包來處理了( the package should be entirely self contained. It won't treat case1/ as a package when you're running main.py inside it.),而cat和dog還是包,并且已經是包樹的頂層了。可想而知,下層的 cat.py (import cat.cat)自然找不到上層包了,想要相對導入成功,必須讓下層的被導入對象是上層包或上層包內的對象。

所以使用相對導入的目錄的平級目錄內的所有py文件不允許單獨執行(當然局部測試時是可以的,而不是將包中的py文件當作主應用程序執行),要保證這個模塊不是入口文件(py文件中有if __name__ == '__main__',其實也不一定有這個,只要你執行就算是),只是作為被導入的模塊才可以以這樣使用。

python 中只能在package中使用相對導入,不能在用戶的應用程序中使用相對導入,因為不論是相對導入還是絕對導入,都是相當于當前模塊來說的,對于用戶的主應用程序,也就是入口文件,模塊名總是為“ __main__ ?”, 所以用戶的應用程序(如NLP目錄下有一個main.py[包含__main__],要執行的)必須使用絕對導入,而package(如__main__調用的包NLP\TargetOpinion)中的導入可以使用相對導入。

When launching a python source file, it is forbidden to import another file, that is in the current package, using relative import.

解決:

1 假設整個項目目錄NLP\TargetOpinion\***;將主程序移出到package(即TargetOpinion\***)外,TargetOpinion中的子packages可以互相相對導入,但是package即TargetOpinion目錄下不能有main模塊,要移到外面,如NLP目錄下,與TargetOpinion平齊。

當然上面案例就是將main.py放到case1平齊的目錄中,如case1_1。

2 如果main.py想放到與TargetOpinion平齊的目錄中,如NLP\test,這時也不能使用..TargetOpinion來調用,但是可以先將NLP目錄加入path:sys.path.append(os.path.join(os.path.split(os.path.realpath(__file__))[0], "..")),再使用TargetOpinion來調用。

報錯2:SystemError: Parent module '' not loaded, cannot perform relative import?

這種情況一般是因為case1不是包(目錄下沒有__init__),而?cat.cat.py要調用dog.dog.py(from ..dog import dog),這樣上層..不是包不能導入出錯。

不過在pycharm中設置source root(或者加入../..到sys.path中)好像也可以解決。

[pycharm快捷鍵、常用設置、配置管理 ]

案例2:

目錄樹
case3/
├── alpaca.py
├── main.py
└── pets
? ? ├── __init__.py
? ? ├── cat
? ? │ ? ├── __init__.py
? ? │ ? └── cat.py
? ? └── dog
? ? ? ? ├── __init__.py
? ? ? ? └── dog.py

代碼
# case3/pets/cat/cat.py
from ..dog import dog
from .. import dog
# case3/main.py
from pets.cat import cat

執行
python case3/main.py

請注意,這里的 cat.py 中是不能導入 alpaca 的,因為 pets 已經是這個包樹的頂層了(case3中包含main.py其中包含main函數,這樣case3就不會被當作包?)。

2.ImportError: No module named '***'

sys.path沒有加入導入的模塊所在目錄

3.忌兩個py文件循環導入

4.?使用相對導入非本級目錄的py也禁止單獨運行

否則報錯: ValueError: Attempted relative import in non-package

[python的relation import]

[python package module import 完全總結]

[python 下 import 模塊使用相對路徑]

在軟件包內部只進行相對導入

在子模塊中你時常見到的一個簡單錯誤,就是使用軟件包的名字來導入軟件包。

# within a sub-module

from a_package import APackageError

這樣做會導致兩個不好的結果:

  1. 子模塊只有當軟件包被安裝在 PYTHONPATH 內才能正確運行。
  2. 子模塊只有當這個軟件包的名字是 a_package 時才能正確運行。

盡管第一條看上去并不是什么大問題,但是考慮一下,如果你在 PYTHONPATH 下的兩個目錄中,有兩個同名的軟件包。你的子模塊可能最終導入了另一個軟件包,你將無意間使得某個或某些對此毫無戒備的程序員(或是你自己)debug 到深夜。

所以說,在軟件包中最好只進行相對導入,而運行的執行文件(__main__)都放在軟件包外面。

AttributeError: 'module' object has no attribute '***'

如import scipy或者import dateutil后

使用scipy.misc或者dateutil.parser出錯

原因:because the parser.py is a module in the dateutil package. It's a separate file in the folder structure.所以要手動添加。其實主要是ubuntu_env/lib/python3.5/site-packages/dateutil$ vi __init__.py中沒有from . import subpackages,自己修改一下就好了,不過它本身沒這么加肯定有它的原因,lz暫時還沒搞清楚。

解決:所以最好還是使用import dateutil.parser或者from dateutil import parser來導入模塊。

[Scipy教程 - python數值計算庫 ]

皮皮blog

?

?

讓模塊保持較小的規模

你的模塊應當比較小。記住,那個使用你軟件包的程序員會在軟件包作用域進行導入,同時你會使用你的?__init__.py?文件來作為一個組織工具,來暴露一個完整的接口。

好的做法是一個模塊只定義一個類,伴隨一些幫助方法和工廠方法來協助建立這個模塊。

class APackageClass(object):

????'''One class'''

def apackage_builder(how_many):

????foriinrange(how_many):

????????yieldAPackageClass()

如果你的模塊暴露了一些方法,把一些相互依賴的方法分為一組放進一個模塊,并且把不相互依賴的方法移動到單獨的模塊中,一個例子是 fsq/enqueue.py,它暴露了一系列的方法來為同一個功能提供不同的接口(就像 simplejson 中的l oad/loads)。盡管這個例子足夠直觀,讓你的模塊保持較小規模需要一些判斷,但是一個好的原則是:當你有疑問的時候,就去創建一個新的子模塊吧。

字節編譯文件.pyc

輸入一個模塊相對來說是一個比較費時的事情,所以Python做了一些技巧,以便使輸入模塊更加快一些。

一種方法是創建 字節編譯的文件 ,這些文件以.pyc作為擴展名。字節編譯的文件與Python變換程序的中間狀態有關。{一個用編譯性語言比如C或C++寫的程序可以從源文件(即C或C++語言)轉換到一個你的計算機使用的語言(二進制代碼,即0和1)。這個過程通過編譯器和不同的標記、選項完成。當你運行你的程序的時候,連接/轉載器軟件把你的程序從硬盤復制到內存中并且運行。而Python語言寫的程序不需要編譯成二進制代碼。你可以直接從源代碼運行 程序。在計算機內部,Python解釋器把源代碼轉換成稱為字節碼的中間形式,然后再把它翻譯成計算機使用的機器語言并運行。}

當你在下次從別的程序輸入這個模塊的時候,.pyc文件是十分有用的——它會快得多,因為一部分輸入模塊所需的處理已經完成了。另外,這些字節編譯的文件也是與平臺無關的。

皮皮blog

模塊內的所有定義

dir()函數

當你為dir()提供一個模塊名的時候,它返回模塊定義的名稱列表(函數、類和變量)。如果不提供參數,它返回當前模塊中定義的名稱列表(當前解釋器中定義的命名)。

>>> import fibo
>>> dir(fibo)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'fib', 'fib2']
>>> dir()
['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'fibo']

dir()并不會列出內置函數和變量名。如果你想列出這些內容,它們在標準模塊__builtin__中定義。

curModuleDir=dir()??#?get?dir?of?current?file(module)同時這句話放在模塊(.py)文件函數或類外面

修改dir函數表現

class Shape(object):

????????def__dir__(self):

????????????return['area','perimeter','location']

則返回指定的三個函數字符串

模塊的__name__屬性

當一個模塊被第一次輸入import的時候,這個模塊的主塊將被運行。假如我們只想在程序本身被使用的時候運行主塊,而在它被別的模塊輸入的時候不運行主塊,這可以通過模塊的__name__屬性完成。

image

每個Python模塊都有它的__name__,如果它是'__main__',這說明這個模塊被用戶單獨運行,我們可以進行相應的恰當操作。

[Python內置函數--dir]

?

Import成功但是pycharm中無法點擊進入

使用torch.utils.data.DataLoader時,pycharm中無法直接點擊進入代碼。

torch.utils Cannot find reference 'utils' in '__init__.pyi

可以通過更新torch到1.6.0解決,但是會出另一個問題:Cannot find reference 'data' in '__init__.pyi

解決方法:同時

import torch
import torch.utils.data? ?#這樣就可以了

from:http://blog.csdn.net/pipisorry/article/details/43313197

ref:簡明python教程-模塊和包

深入Python模塊的使用

構建健壯 Python 包的 5 個簡單規則

深扒Python是如何找到模塊的?

?

?

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/194087.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息