簡體   English   中英

為什么我必須使用python中的電子郵件模塊“從模塊導入”?

[英]Why do I have to “from module import” with the email module in python?

抱歉,如果沒有找到問題,我很難正確地表達這個問題。

我正在嘗試使用電子郵件模塊創建簡單的純文本電子郵件,並在滿足某些條件時將其發送。 我遇到了各種異常行為,並希望了解它。 我首先從官方示例( https://docs.python.org/3.4/library/email-examples.html )中提取了一個簡單的測試,它運行良好。 當我開始嘗試在我的項目中實現這一目標時,我開始得到各種各樣的"'module' object has no attribute 'something'" 我可以運行這樣的東西,並且效果很好

import email
import smtplib

# Create message object
msg = email.message.EmailMessage()

# Create the from and to Addresses
from_address = email.headerregistry.Address("Stack of Pancakes", "pancakes@gmail.com") 
to_address = email.headerregistry.Address("Joe", "pythontest@mailinator.com")

# Create email headers
msg['Subject'] = "subject of email"
msg['From'] = from_address
msg['To'] = to_address

#
email_content = "This is a plain text email"
msg.set_content(email_content)

server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login("pancakes@gmail.com", "password")
server.send_message(msg)
server.quit()

這很完美。 但是,如果我以不同的順序訂購東西,事情就會開始崩潰,我不明白為什么。 例如,如果我將from_addressto_address行放在像這樣調用EmailMessage的上方

import email
import smtplib

# Create the from and to Addresses
from_address = email.headerregistry.Address("Stack of Pancakes", "pancakes@gmail.com") 
to_address = email.headerregistry.Address("Joe", "pythontest@mailinator.com")

# Create message object
msg = email.message.EmailMessage()

... other code

失敗的原因是'module' object has no attribute 'headerregistry' 為什么創建EmailMessage會使其他代碼正常運行?

實際上,如果我有一個僅包含此文件的文件

import email

to_address = email.headerregistry.Address("joe", "joe@joe.com")

它失敗,並顯示相同的錯誤。

要運行該小片段,我必須這樣做

from email.headerregistry import Address

to_address = Address("joe", "joe@joe.com")

或者,這真的很奇怪,我可以讓它運行

import email
import smtplib

email.message.EmailMessage()
to_address = email.headerregistry.Address("joe", "joe@joe.com")

但是,即使刪除了這4行中的smtplib中的任何內容,如果我刪除了import smtplib它也會再次失敗。


我敢肯定,我可以繼續嘗試所有我能想到的組合,並使其正常運行,但是我更希望了解這種行為。 這樣,我將更有信心在生產環境中運行代碼。

為什么我不能只調用import email並用email.headderregistry.Address聲明對象,為什么我必須from email.headerregistry import Address顯式地導入特定功能? 為什么使用import smtplib編譯,但是沒有它會失敗。 為什么僅在調用EmailMessage()后才起作用?

通常,我真的很擅長尋找答案,但是我認為在這種情況下,我只是不知道要搜索什么。 對於“模塊對象沒有屬性”,有很多解決方案,但是大多數解決方案是重復的命名文件,循環導入,調用不存在的函數或檢查屬性是否存在。 他們似乎都沒有解決導入行為的工作方式。 我是否在構造代碼錯誤,還是電子郵件模塊只是對我起作用?

import email不會自動導入email包中的所有模塊。 這意味着,要使用email.headerregistry ,必須將其導入,可以很簡單:

import email.headerregistry

之后,您將可以使用email.headerregistry.Address

from email.headerregistry import Address寫入后,您的代碼也可以工作,因為該語句在內部(等同於) import email.headerregistry以便加載模塊並保留Address 同樣, smtplib導入與email相關的模塊,其中一些可能會導入email.headerregistry

總結一下:一旦任何模塊執行了email.headerregistry導入,即使從未明確請求email.headerregistry 所有模塊 ,該子模塊也對所有導入email 模塊可見。 導入模塊可以使無關包的子模塊成為副作用的事實可能導致討厭的錯誤,即只有在其他模塊之后才導入模塊,模塊才能工作。 幸運的是,諸如pylint和Eclipse的pydev之類的現代工具很好地解決了這種陷阱。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM