2014-07-03 88 views
1

对不起,如果问题不在现场,我很难妥善解答这个问题。为什么我必须使用python中的email模块“从模块导入”?

我试图使用电子邮件模块来创建一个简单的纯文本电子邮件,并在满足特定条件时发送它。我遇到各种不正常的行为,并想了解它。我开始从官方示例(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", "[email protected]") 
to_address = email.headerregistry.Address("Joe", "[email protected]") 

# 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("[email protected]", "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", "[email protected]") 
to_address = email.headerregistry.Address("Joe", "[email protected]") 

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

... other code 

它失败'module' object has no attribute 'headerregistry'。为什么EmailMessage创建允许其他代码正常工作?

事实上,如果我有一个包含文件,仅此

import email 

to_address = email.headerregistry.Address("joe", "[email protected]") 

它失败,出现同样的错误。

为了得到小片段跑我不得不这样做

from email.headerregistry import Address 

to_address = Address("joe", "[email protected]") 

或者,这是非常奇怪的,我能得到这个运行

import email 
import smtplib 

email.message.EmailMessage() 
to_address = email.headerregistry.Address("joe", "[email protected]") 

,但如果我删除import smtplib它会再次失败,即使我在这4行中没有使用smtplib中的任何内容。


我相当肯定我只能继续努力,每一个组合我能想到的,并让它正常工作,但我更愿意理解的行为。这样我就会对在生产环境中运行代码感到更加自信。

为什么我不能拨打import email并用email.headderregistry.Address声明我的对象,为什么我必须明确导入具有from email.headerregistry import Address的特定功能?为什么它编译与import smtplib但没有它失败。为什么只有在调用EmailMessage()之后才能正常工作?

通常我很擅长寻找答案,但我认为在这种情况下,我只是不知道要寻找什么。 “模块对象没有属性”有很多解决方案,但其中大多数是重复的命名文件,循环导入,调用不存在的函数或检查属性是否存在。他们似乎没有解决进口行为如何运作。我是否构建了错误的代码,或者是电子邮件模块只是对我起作用?

+2

是您的脚本名为'email.py'? :)我之前就被绊了一跤,在系统模块后命名我的模块。 – johntellsall

+0

您可能在某处发生了小的剪切和粘贴错误,因为您的原始代码块不能按所述方式工作。它需要'from email.message import EmailMessage from email.headerregistry import Address' –

+0

@shavenwarthog不,我在我的最后一段中提到了这一点。 –

回答

5

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,即使他们从来没有明确要求email.headerregistry。导入模块的事实可能导致无关包的子模块可用作副作用,这可能会导致令人讨厌的错误,其中模块仅在其他模块后导入时才工作。幸运的是,像pylint和Eclipse的pydev这样的现代工具很好地解决了这种陷阱。

+0

这解决了大部分问题。任何想法为什么当你尝试在email.message.EmailMessage()之前调用'email.headderregistry.Address'时会失败,但是如果你先调用EmailMessage(),那么工作正常吗? –

+0

@StackofPancakes我期望首次实例化EmailMessage导致导入'email.headerregistry'。 – user4815162342

+0

谢谢,这是我第一次遇到一个模块,在使用'import module_name'后出现如此奇怪的表现。我想在未来我会直接导入一个模块的特定部分,如果我再次遇到这种情况。 –

相关问题