使用 zipfile zlib python 和 mailgun 时,Mailgun 仅在 Python 脚本中发送部分 zip 文件

Posted

技术标签:

【中文标题】使用 zipfile zlib python 和 mailgun 时,Mailgun 仅在 Python 脚本中发送部分 zip 文件【英文标题】:Mailgun only sends partial zip file in Python script when using zipfile zlib python and mailgun 【发布时间】:2016-02-26 19:41:28 【问题描述】:

编辑:我尝试实现 gzip,但无法使其与 zipfile 库一起使用。文档似乎表明 zlib 是唯一兼容的库。我还尝试重新安装 zlib。

我创建的 Python 脚本遇到了一个奇怪的问题。该脚本的重点是从 SQL 服务器中提取一些数据,将其转储为 CSV,将其压缩(压缩)并通过 Mailgun API 发送电子邮件。

如果我在没有 zlib 压缩的情况下压缩文件,mailgun 会提取整个 zip 文件(包含测试数据的 14mb)并通过电子邮件成功发送。我可以从电子邮件和我的本地文件系统下载 zip 文件,并在其中打开 csv 文件而不会出现问题。

但是一旦我添加了 zipfile.ZIP_DEFLATED 压缩方法,我就会遇到问题。生成的 zip 在我的本地文件系统上下降到 365kb,并且可以正常打开。但是当我查看生成的电子邮件时,zip 文件的大小被严重截断,约为 865 字节。如果我尝试下载并打开它,我会从 Windows 收到“这不是一个有效的 zip 文件”错误。

为什么 Mailgun 会发送完整的未压缩 zip,而不是压缩的 zip,即使它在我的文件系统上可以正常打开?即使代码显然是同步的,我也尝试过一件疯狂的事情,就是在函数调用之间添加暂停,以防压缩需要更多时间。这没有帮助。

代码如下,为简洁起见已剪辑。

import pyodbc
import unicodecsv
import time
import requests
import zipfile
import zlib

now = time.localtime(time.time())
today = time.strftime("%Y-%m-%d %H%M%p", now)

filename_sql1 = "SCORM Courses " + today
filename_sql2 = "Non-SCORM Courses " + today

print "ready...."

class ODBCtoCSV(object):

    def __init__(self):

    def getEncodedData (self, doubleList):
        data=struct.pack(len(doubleList) * 'd', *doubleList)
        return base64.b64encode(data)

    def dump(self, sql, filename, include_headers=True):
        f = unicodecsv.writer(file(filename + ".csv", 'wb'))

        cnxn = pyodbc.connect(self.connect_string)
        c = cnxn.cursor()
        c.execute(sql)

        if include_headers:
            f.writerow([d[0] for d in c.description])


            f.writerows(c.fetchall())
            cnxn.close()

def generatereport(s, filename):

    print "Processing %s" % (filename)
    if __name__ == '__main__':

        query = ODBCtoCSV()
        query.dump(s, filename)
        f = open(filename + ".csv", 'rb')


def zippy(filename):
    zf = zipfile.ZipFile(filename + ".zip", "w", zipfile.ZIP_DEFLATED)
    zf.write(filename + ".csv")
    zf.close()


def send_notification_message(filename):
    return requests.post(
        "xxxxxxx",
        auth=("api", "xxxx"),
        files=[("attachment", open(filename + ".zip"))],
        data="from": "xxxxxxx",
              "to": ["xxxxxx"],
              "subject": " Reports are Available",
              "text": "This is an automated message. The reports have run successfully and are available via attachment.",
              "html": "<p><b>This is an automated message.</b></p><p>The reports have run successfully and are available via attachment.</p>",
              "o:tag": "xxxxxx")        

generatereport(sql1, filename_sql1)
zippy(filename_sql1)
print filename_sql1 + "Succesfully generated"
generatereport(sql2, filename_sql2)
zippy(filename_sql2)
print filename_sql2 + "Succesfully generated"
send_notification_message(filename_sql1)
send_notification_message(filename_sql2)

exit

【问题讨论】:

【参考方案1】:

我通过在 Mailgun 调用中将模式文件 IO 模式更改为“rb”解决了这个问题。

我不确定为什么它适用于未压缩的 zip 文件,但仍然不能用于压缩的 zip 文件。修改后的代码如下。

files=[("attachment", open(filename + ".zip", "rb"))],

【讨论】:

以上是关于使用 zipfile zlib python 和 mailgun 时,Mailgun 仅在 Python 脚本中发送部分 zip 文件的主要内容,如果未能解决你的问题,请参考以下文章

tomcat 启动异常 EOFException: Unexpected end of ZLIB input stream

python模块 zipfile

python3中zipfile模块的常用方法

python zipfile 文件压缩和文件

无法使用 python 创建 ZIPfile

Python学习第九篇:zipfile 库操作压缩包