如何编译使用boto访问S3的Python代码?

2 投票
3 回答
2207 浏览
提问于 2025-04-16 04:49

我正在尝试把一个简单的Python程序编译成一个可以分享的.exe文件,这个程序是用boto包上传文件到S3存储桶的。我对任何编译方法都持开放态度。目前我已经尝试过bbfreezepy2exe这两种工具,但结果都是一样的。出问题的代码大致如下:

import boto
#...snip...
fname_base = os.path.basename(fname)
s3 = boto.connect_s3(aws_access_key_id=_aws_key, aws_secret_access_key=_aws_secret_key, is_secure=False);
bucket = s3.get_bucket(_bucket)
key = bucket.new_key(fname_base)
key.set_contents_from_filename(fname)

用这两种工具编译后运行,我得到的结果是:

Traceback (most recent call last):
  File "s3stash.py", line 238, in <module>
    sys.exit(main())
  File "s3stash.py", line 225, in main
    push_file_to_s3(f, options)
  File "s3stash.py", line 160, in push_file_to_s3
    _push_with_boto(fname)
  File "s3stash.py", line 148, in _push_with_boto
    s3 = boto.connect_s3(aws_access_key_id=_aws_key, aws_secret_access_key=_aws_secret_key, is_secure=False);
  File "boto\__init__.pyo", line 104, in connect_s3
  File "zipextimporter.pyo", line 82, in load_module
  File "boto\s3\connection.pyo", line 27, in <module>
  File "zipextimporter.pyo", line 82, in load_module
  File "boto\utils.pyo", line 55, in <module>
  File "email\__init__.pyo", line 79, in __getattr__
ImportError: No module named multipart

我在Windows XP SP3上使用的是ActiveState Python 2.6。boto包是通过以下方式安装的:

easy_installer --always-unzip boto

我使用了--always-unzip这个选项,因为我在这里看到关于py2exe处理解压的egg文件有问题。不幸的是,即使我用bb-freeze来构建可执行文件,得到的错误也是一样的。

py2exe的输出中,接近结尾的地方有以下信息:

The following modules appear to be missing
['_scproxy', 'email.Encoders', 'email.MIMEBase', 'email.MIMEMultipart', 'email.MIMEText', 'email.Utils', 'simplejson']

这给了一些线索。我尝试了其他帖子中建议的方法,特别是当用py2exe编译时推荐使用-i选项,但可惜没有任何帮助。在那些问题中,用户自己明确地包含了email子模块。我没办法把那些解决方案适应到我的情况中,单单用-i添加它们也没能阻止py2exe警告我缺少模块,或者导致生成的exe因为缺少模块而失败。

有人能帮我把这个代码打包成可以分享的版本吗?

3 个回答

1

我成功用boto和py2exe创建了一个可用的exe文件。

接下来,把下面的代码加到你的script.py里:

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

接下来遇到的问题是HTTPS连接,似乎py2exe在某种程度上“隐藏”了证书文件。解决这个问题的方法有两个:

1) 使用HTTP

或者

2) 不检查证书

1) 使用HTTP

conn = boto.connect_dynamodb(
    aws_access_key_id = ' ',
    aws_secret_access_key = ' ', 
    is_secure = False)

这里的“is_secure = False”非常重要。

2) 不检查证书

conn = boto.connect_dynamodb(
    aws_access_key_id = ' ',
    aws_secret_access_key = ' ', 
    is_secure = True, 
    validate_certs = False)

这里的“validate_certs = False”也非常重要。

如果有人找到解决证书验证错误的方法,请回复我!

1

我知道这个问题已经很久了,但我也遇到过同样的问题,并且在使用py2exe和py2app的时候解决了它。只需要在你的setup.py文件中使用'packages'选项,而不是'includes'选项:

extra = {}
mainscript = "foo/__main__.py"

if is_os_x():
    extra["setup_requires"] =['py2app']
    extra["app"] = [mainscript]
    extra["options"] = { "py2app": {
        "packages": ['email'],
        }                                       
    }

elif is_windows():
    extra["setup_requires"] =['py2exe']
    extra['console'] = [mainscript]
    extra['options'] = {'py2exe': {
        # Includes that py2exe doesn't include automatically
       'packages': ['email'],
       }
    }

setup(
    # snip
    ** extra
)   

希望这能帮到你。

1

我实际上让这个问题解决了。答案是放弃使用boto,而是改用poster库。我仍然使用boto来生成一个签名的策略和一些必要的表单字段,这些是通过poster来完成的,但真正执行POST请求的部分现在只用poster。因为只用poster,所以py2exe在为我创建一个可以重新分发的独立可执行文件时没有任何问题。

撰写回答