簡體   English   中英

使用Windows python 2.3進行的poplib重構

[英]Incoming poplib refactoring using windows python 2.3

嗨,伙計們,請你幫我重構一下,這樣才能讓它變得更加詭異。

import sys
import poplib
import string
import StringIO, rfc822
import datetime
import logging

def _dump_pop_emails(self):
    self.logger.info("open pop account %s with username: %s" % (self.account[0], self.account[1]))
    self.popinstance = poplib.POP3(self.account[0])
    self.logger.info(self.popinstance.getwelcome()) 
    self.popinstance.user(self.account[1])
    self.popinstance.pass_(self.account[2])
    try:
        (numMsgs, totalSize) = self.popinstance.stat()
        for thisNum in range(1, numMsgs+1):
            (server_msg, body, octets) = self.popinstance.retr(thisNum)
            text = string.join(body, '\n')
            mesg = StringIO.StringIO(text)                               
            msg = rfc822.Message(mesg)
            name, email = msg.getaddr("From")
            emailpath = str(self._emailpath + self._inboxfolder + "\\" + email + "_" + msg.getheader("Subject") + ".eml")
            emailpath = self._replace_whitespace(emailpath)
            file = open(emailpath,"wb")
            file.write(text)
            file.close()
            self.popinstance.dele(thisNum)
    finally:
        self.logger.info(self.popinstance.quit())

def _replace_whitespace(self,name):
    name = str(name)
    return name.replace(" ", "_")   

同樣在_replace_whitespace方法中,我希望有一些清理程序,它可以取出所有可能導致處理的非法字符。

基本上我想以標准方式將電子郵件寫入收件箱目錄。

我在這里做錯了嗎?

我沒有看到該代碼有任何重大錯誤 - 它是否表現不正確,或者您只是在尋找一般風格指南?

幾點說明:

  1. 而不是logger.info ("foo %s %s" % (bar, baz)) ,使用"foo %s %s", bar, baz 如果不打印消息,這可以避免字符串格式化的開銷。
  2. try...finally打開emailpath
  3. 使用'\\n'.join (body) ,而不是string.join (body, '\\n')
  4. 而不是msg.getaddr("From") ,只是msg.From

這不是重構(據我所知,它不需要重構),但有些建議:

您應該使用電子郵件包而不是rfc822。 用email.Message替換rfc822.Message,並使用email.Utils.parseaddr(msg [“From”])獲取名稱和電子郵件地址,並使用msg [“Subject”]來獲取主題。

使用os.path.join創建路徑。 這個:

emailpath = str(self._emailpath + self._inboxfolder + "\\" + email + "_" + msg.getheader("Subject") + ".eml")

變為:

emailpath = os.path.join(self._emailpath + self._inboxfolder, email + "_" + msg.getheader("Subject") + ".eml")

(如果self._inboxfolder以斜杠開頭,或者self._emailpath以1開頭,則可以用逗號替換第一個+)。

它並沒有真正傷害任何東西,但你可能不應該使用“file”作為變量名,因為它會影響內置類型(像pylint或pychecker這樣的檢查器會警告你)。

如果你沒有在這個函數之外使用self.popinstance(假設你在函數中連接和退出似乎不太可能),那么就沒有必要將它作為self的一個屬性。 只需使用“popinstance”。

使用xrange而不是range。

而不是只導入StringIO,執行以下操作:

try:
    import cStringIO as StringIO
except ImportError:
    import StringIO

如果這是一個可以由多個客戶端一次訪問的POP郵箱,則可能需要在RETR調用周圍放置try / except,以便在無法檢索一條消息時繼續。

正如約翰所說,使用“\\ n”.join而不是string.join,使用try / finally僅在文件打開時關閉文件,並分別傳遞日志記錄參數。

我能想到的一個重構問題是你不需要解析整個消息,因為你只是轉儲原始字節的副本,而你想要的只是From和Subject標題。 您可以使用popinstance.top(0)來獲取標題,從中創建消息(空白正文),並將其用於標題。 然后執行完整的RETR來獲取字節。 如果您的消息很大(這樣解析它們需要很長時間),這只會值得做。 在進行此優化之前,我肯定會測量。

對於您的名稱清理功能,它取決於您希望名稱有多好,以及您確定電子郵件和主題使文件名唯一(看起來不太可能)。 你可以這樣做:

emailpath = "".join([c for c in emailpath if c in (string.letters + string.digits + "_ ")])

而你最終只會使用字母數字字符和下划線和空格,這看起來像一個可讀的集合。 鑒於您的文件系統(使用Windows)可能不區分大小寫,您也可以小寫(在末尾添加.lower())。 如果你想要更復雜的東西,你可以使用emailpath.translate。

繼續我對約翰回答的評論

我發現問題是什么,名稱字段和主題字段中存在非法字符,這導致python在看到“:”和“/”之后嘗試將電子郵件編寫為目錄而導致打嗝。

約翰點4號不起作用! 所以我像以前一樣離開了。 也是第1點正確,我是否正確實施了您的建議?

def _dump_pop_emails(self):
    self.logger.info("open pop account %s with username: %s", self.account[0], self.account[1])
    self.popinstance = poplib.POP3(self.account[0])
    self.logger.info(self.popinstance.getwelcome()) 
    self.popinstance.user(self.account[1])
    self.popinstance.pass_(self.account[2])
    try:
        (numMsgs, totalSize) = self.popinstance.stat()
        for thisNum in range(1, numMsgs+1):
            (server_msg, body, octets) = self.popinstance.retr(thisNum)
            text = '\n'.join(body)
            mesg = StringIO.StringIO(text)                               
            msg = rfc822.Message(mesg)
            name, email = msg.getaddr("From")
            emailpath = str(self._emailpath + self._inboxfolder + "\\" + self._sanitize_string(email + " " + msg.getheader("Subject") + ".eml"))
            emailpath = self._replace_whitespace(emailpath)
            print emailpath
            file = open(emailpath,"wb")
            file.write(text)
            file.close()
            self.popinstance.dele(thisNum)
    finally:
        self.logger.info(self.popinstance.quit())

def _replace_whitespace(self,name):
    name = str(name)
    return name.replace(" ", "_")   

def _sanitize_string(self,name):
    illegal_chars = ":", "/", "\\"
    name = str(name)
    for item in illegal_chars:
        name = name.replace(item, "_")
    return name

暫無
暫無

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

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