How to compile python code that uses boto to access S3? - python

I'm trying to compile a simple Python program, that uploads files to an S3 bucket using the boto package, in to a single, redistributable .exe file. I'm open to any compilation method. So far I've tried both bbfreeze and py2exe and both yield the same results. The code in question that causes trouble looks like this:
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)
Compiled with either executable bundling utility and run I get:
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
I'm using ActiveState Python 2.6 on Windows XP SP3. The boto package was installed with:
easy_installer --always-unzip boto
I used the --always-unzip option based on the information found here about py2exe having issues with the egg files that were unpacked. Unfortunately the error I get is the same when I use bb-freeze to build the executable.
The output from py2exe includes, near the end, the following bit of information:
The following modules appear to be missing
['_scproxy', 'email.Encoders', 'email.MIMEBase', 'email.MIMEMultipart', 'email.MIMEText', 'email.Utils', 'simplejson']
Which lends some hints. I tried methods suggested in other posts to SO where the -i option was recommended when compiling with py2exe and unfortunately nothing helped. In those other questions the users were doing their own explicit inclusion of of the email sub-modules. I could not figure how to adapt those solutions to my case unfortunately and just adding them with -i didn't stop py2exe from warning me of the missing modules, or the resulting bundled exe from failing with the missing module error.
Can someone help me get this code bundled for redistribution?

I actually got this to work. The answer was to ditch boto and use the poster library instead. I still use boto to generate a signed policy and the necessary form fields for POST I do via poster, but the actual executable that does the POST only includes poster now. With just poster in the mix, py2exe doesn't have any issues creating a standalone executable for me for redistribution.

I know this is an old question, but I had the same problem and fixed it while still using py2exe and py2app. Just use the 'packages' option instead of the 'includes' option in your setup.py:
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
)
Hope that helps.

I've managed to create working exe with boto & py2exe
Add to your script.py
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
Next error is with HTTPS connection, it seems that py2exe is "hiding" cert file somehow..
The way to fix this is
1) use HTTP
OR
2) dont check certs
1) HTTP
conn = boto.connect_dynamodb(
aws_access_key_id = ' ',
aws_secret_access_key = ' ',
is_secure = False)
"is_secure = False" is crutial
2) DONT CHECK CERTS
conn = boto.connect_dynamodb(
aws_access_key_id = ' ',
aws_secret_access_key = ' ',
is_secure = True,
validate_certs = False)
"validate_certs = False" is crutial
If someone figures out how to fix error in cert validation, please reply !

Related

error using pip search (pip search stopped working)

I am getting this error in pip search while studying python.
The picture is an error when I pip search. Can you tell me how to fix it?
$ pip search pdbx
ERROR: Exception:
Traceback (most recent call last):
File "*/lib/python3.7/site-packages/pip/_internal/cli/base_command.py", line 224, in _main
status = self.run(options, args)
File "*/lib/python3.7/site-packages/pip/_internal/commands/search.py", line 62, in run
pypi_hits = self.search(query, options)
File "*/lib/python3.7/site-packages/pip/_internal/commands/search.py", line 82, in search
hits = pypi.search({'name': query, 'summary': query}, 'or')
File "/usr/lib/python3.7/xmlrpc/client.py", line 1112, in __call__
return self.__send(self.__name, args)
File "/usr/lib/python3.7/xmlrpc/client.py", line 1452, in __request
verbose=self.__verbose
File "*/lib/python3.7/site-packages/pip/_internal/network/xmlrpc.py", line 46, in request
return self.parse_response(response.raw)
File "/usr/lib/python3.7/xmlrpc/client.py", line 1342, in parse_response
return u.close()
File "/usr/lib/python3.7/xmlrpc/client.py", line 656, in close
raise Fault(**self._stack[0])
xmlrpc.client.Fault: <Fault -32500: 'RuntimeError: This API has been temporarily disabled due to unmanageable load and will be deprecated in the near future. Please use the Simple or JSON API instead.'>
The pip search command queries PyPI's servers, and PyPI's maintainers have explained that the API endpoint that the pip search command queries is very resource intensive and too expensive for them to always keep open to the public. Consequently they sometimes throttle access and are actually planning to remove it completely soon.
See this GitHub issues thread ...
The solution I am using for now is to pip install pip-search (a utility created by GitHub user #victorgarric).
So, instead of 'pip search', I use pip_search. Definitely beats searching PyPI via a web browser
Follow the suggestion from JRK at the discussion at github (last comment) the search command is temporarily disabled, use your browser to search for packages meanwhile:
Check the thread on github and give him a thumb up ;)
search on website, https://pypi.org/,
then install the package you wanted
The error says
Please use the Simple or JSON API instead
You can try pypi-simple to query the pip repository
https://pypi.org/project/pypi-simple/
It gives an example too, I tried to use it here:
pypi-simple version 0.8.0 DistributionPackage' object has no attribute 'get_digest':
!/usr/bin/env python3
-*- coding: utf-8 -*-
"""
Created on Thu Nov 11 17:40:03 2020
#author: Pietro
"""
from pypi_simple import PyPISimple
def simple():
package=input('\npackage to be checked ')
try:
with PyPISimple() as client:
requests_page = client.get_project_page(package)
except:
print("\n SOMETHING WENT WRONG !!!!! \n\n",
"CHECK INTERNET CONNECTION OR DON'T KNOW WHAT HAPPENED !!!\n")
pkg = requests_page.packages[0]
print(pkg)
print(type(pkg))
print('\n',pkg,'\n')
print('\n'+pkg.filename+'\n')
print('\n'+pkg.url+'\n')
print('\n'+pkg.project+'\n')
print('\n'+pkg.version+'\n')
print('\n'+pkg.package_type+'\n')
#print('\n'+pkg.get_digest()+'\n','ENDs HERE !!!!') #wasnt working
if __name__ == '__main__':
simple()
got -4 so far for this answer don't know why , figureout I can try to check for a package with:
# package_name = input('insert package name : ')
package_name = 'numpy'
import requests
url = ('https://pypi.org/pypi/'+package_name+'/json')
r = requests.get(url)
try:
data = r.json()
for i in data:
if i == 'info':
print('ok')
for j in data[i]:
if j == 'name':
print((data[i])[j])
print([k for k in (data['releases'])])
except:
print('something went south !!!!!!!!!!')

configparser.NoSectionError:No section:'XXX'

I want to configure a config. ini and read it. When I run the code in pycharm, it's okay and it returns the result normally. But when I use pyinstaller to package .PY into an .EXE file, it will report an error:
Congparser.NosectionError: No section:'config'
If there are any suggestions, I would be very grateful.
By the way, the. EXE file and. INI file are in the same folder,
I use Python3.7 on Windows10
I'm a Python rookie. I don't know how to solve the error in cmd. I try to output the path in pycharm. The result is very normal.
# coding = gbk
import configparser
import os
curpath = os.path.dirname(os.path.realpath(__file__))
cfgpath = os.path.join(curpath, "config.ini")
print(cfgpath)
print(os.path.realpath(__file__))
conf = configparser.ConfigParser()
conf.read(cfgpath)
items = conf.items('config')
l2 = [items[0][1],items[1][1],items[2][1],items[3][1]]
print(items)
print(l2)
Results in pycharm:
E:\untitled\venv\Custom_formula\config.ini
E:\untitled\venv\Custom_formula\config_data.py
[('server', '127.0.0.1'), ('user', 'sa'), ('pwd', '123456'), ('db', 'test')]
['127.0.0.1', 'sa', '123456', 'test']
Results in CMD:
Traceback (most recent call last):
File "config_data.py", line 25, in <module>
File "configparser.py", line 848, in items
configparser.NoSectionError: No section: 'config'
[9080] Failed to execute script config_data
Thanks for Rolf of Saxony! I solved this problem by change
curpath = os.path.dirname(os.path.realpath(__file__))
to
curpath = os.path.dirname(os.path.realpath(sys.argv[0]))
it turns out that the resluts in pycharm are different from those in EXE,
hopefully this will help more people

keyring module is not included while packaging with py2exe

I am making an app using python 2.7 on windows and keyring-3.2.1 . In my python code on eclipse, I used
import keyring
keyring.set_password("service","jsonkey",json_res)
json_res= keyring.get_password("service","jsonkey")
is working fine as I am storing json response in keyring. But, when I converted python code into exe by using py2exe, it shows import error keyring while making dist. Please suggest how to include keyring in py2exe.
Traceback (most recent call last):
File "APP.py", line 8, in <module>
File "keyring\__init__.pyc", line 12, in <module>
File "keyring\core.pyc", line 15, in <module>
File "keyring\util\platform_.pyc", line 4, in <module>
File "keyring\util\platform.pyc", line 29, in <module>
AttributeError: 'module' object has no attribute 'system'
platform_.py code is :
from __future__ import absolute_import
import os
import platform
def _data_root_Windows():
try:
root = os.environ['LOCALAPPDATA']
except KeyError:
# Windows XP
root = os.path.join(os.environ['USERPROFILE'], 'Local Settings')
return os.path.join(root, 'Python Keyring')
def _data_root_Linux():
"""
Use freedesktop.org Base Dir Specfication to determine storage
location.
"""
fallback = os.path.expanduser('~/.local/share')
root = os.environ.get('XDG_DATA_HOME', None) or fallback
return os.path.join(root, 'python_keyring')
# by default, use Unix convention
data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux)
platform.py code is:
import os
import sys
# While we support Python 2.4, use a convoluted technique to import
# platform from the stdlib.
# With Python 2.5 or later, just do "from __future__ import absolute_import"
# and "import platform"
exec('__import__("platform", globals=dict())')
platform = sys.modules['platform']
def _data_root_Windows():
try:
root = os.environ['LOCALAPPDATA']
except KeyError:
# Windows XP
root = os.path.join(os.environ['USERPROFILE'], 'Local Settings')
return os.path.join(root, 'Python Keyring')
def _data_root_Linux():
"""
Use freedesktop.org Base Dir Specfication to determine storage
location.
"""
fallback = os.path.expanduser('~/.local/share')
root = os.environ.get('XDG_DATA_HOME', None) or fallback
return os.path.join(root, 'python_keyring')
# by default, use Unix convention
data_root = globals().get('_data_root_' + platform.system(), _data_root_Linux)
The issue you're reporting is due to an environment that contains invalid modules, perhaps from an improper installation of one version of keyring over another. You will want to ensure that you've removed remnants of the older version of keyring. In particular, make sure there's no file called keyring\util\platform.* in your site-packages.
After doing that, however, you'll encounter another problem. Keyring loads its backend modules programmatically, so py2exe won't detect them.
To work around that, you'll want to add a 'packages' declaration to your py2exe options to specifically include the keyring.backends package. I invoked the following setup.py script with Python 2.7 to convert 'app.py' (which imports keyring) to an exe:
from distutils.core import setup
import py2exe
setup(
console=['app.py'],
options=dict(py2exe=dict(
packages='keyring.backends',
)),
)
The resulting app.exe will import and invoke keyring.

Fixing SSL certificate error in exe compiled with py2exe (or PyInstaller)

I've just finished testing a Python programme which involves logging into a site and requires a CSRF cookie to be set. I've tried packaging it as an exe using py2exe and got a socket error. I have the same problem when I try with PyInstaller. Googling the Errno I found a few other people with the same problem and so I know the problem is to do with the location of SLL certificates.
This is my site_agent class including the logging calls.
class site_agent:
self.get_params()
URL = root_url + '/accounts/login/'
# Retrieve the CSRF token first
self.agent = requests.session()
self.agent.get(URL) # retrieves the cookie # This line throws the error
self.csrftoken = self.agent.cookies['csrftoken']
# Set up login data including the CSRF cookie
login_data = {'username': self.username,
'password': self.password,
'csrfmiddlewaretoken' : self.csrftoken}
# Log in
logging.info('Logging in')
response = self.agent.post(URL, data=login_data, headers=hdr)
The error comes at the self.agent.get(URL) line and the Traceback shows:
Traceback (most recent call last):
File "<string>", line 223, in <module>
File "<string>", line 198, in main
File "<string>", line 49, in __init__
File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.sessions", line 350, in get
File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.sessions", line 338, in requ
est
File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.sessions", line 441, in send
File "C:\pyinstaller-2.0\pyinstaller-2.0\autoresponder\b
uild\pyi.win32\autoresponder\out00-PYZ.pyz\requests.adapters", line 331, in send
requests.exceptions.SSLError: [Errno 185090050] _ssl.c:336: error:0B084002:x509
certificate routines:X509_load_cert_crl_file:system lib
Does this mean that the problem is in requests.adapters?
If so, can I just edit it in my installed Python packages to look for cacert.pem somewhere else, rebuild my exe with py2exe or PyInstaller, then change it back in my installed version of Python?
EDIT
I now have the programme running after compiling with PyInstaller and setting verify=False in all requests.get() and requests.post() calls. But SSL is there for a a reason and I'd really like to be able to fix this error before letting anyone use the tool.
This can be solved easily if you are using "requests" module.
1) Place the below code in your main python file where "requests" module is used
os.environ['REQUESTS_CA_BUNDLE'] = "certifi/cacert.pem"
2) Within your distributable folder where exe is present, create a folder called "certifi" and place the "cacert.pem" file within it.
3) You can find the "cacert.pem" file by
pip install certifi
import certifi
certifi.where()
Awesome.. now your distributable includes the necessary certificates to validate ssl calls.
If using pyinstaller... create a hook-requests.py file in PyInstaller\hooks\ for the requests lib containing
from hookutils import collect_data_files
# Get the cacert.pem
datas = collect_data_files('requests')
In addition to the answer given by frmdstryr, I had to tell requests where the cacert.pem is. I added the following lines right after my imports:
# Get the base directory
if getattr( sys , 'frozen' , None ): # keyword 'frozen' is for setting basedir while in onefile mode in pyinstaller
basedir = sys._MEIPASS
else:
basedir = os.path.dirname( __file__ )
basedir = os.path.normpath( basedir )
# Locate the SSL certificate for requests
os.environ['REQUESTS_CA_BUNDLE'] = os.path.join(basedir , 'requests', 'cacert.pem')
This solution is derived from this link: http://kittyandbear.net/python/pyinstaller-request-sslerror-manual-cacert-solution.txt
I was struggling with this as well, The hook-requests.py provided by frmdstryr did not work for me. But this modified one did:
from PyInstaller.utils.hooks import collect_data_files
# Get the cacert.pem
datas = collect_data_files('certifi')

Using psyco with py2exe?

In my main script, lets call this MyScript.py, I have it like this:
import psyco
psyco.full()
And then my setup.py looks like this:
from distutils.core import setup
import py2exe, sys, os, glob
sys.argv.append('py2exe')
import psyco #speed up compilation
psyco.full()
def find_data_files(source,target,patterns):
"""Locates the specified data-files and returns the matches
in a data_files compatible format.
source is the root of the source data tree.
Use '' or '.' for current directory.
target is the root of the target data tree.
Use '' or '.' for the distribution directory.
patterns is a sequence of glob-patterns for the
files you want to copy.
"""
if glob.has_magic(source) or glob.has_magic(target):
raise ValueError("Magic not allowed in src, target")
ret = {}
for pattern in patterns:
pattern = os.path.join(source,pattern)
for filename in glob.glob(pattern):
if os.path.isfile(filename):
targetpath = os.path.join(target,os.path.relpath(filename,source))
path = os.path.dirname(targetpath)
ret.setdefault(path,[]).append(filename)
return sorted(ret.items())
setup(
name="MyScript",
version="1.0",
description="a script that does something",
author="Keelx",
data_files=find_data_files('.','',[
'gfx/*',
'data/*',
]),
options={'py2exe': {'bundle_files': 1,'optimize': 2}},
windows=[{'script': "MyScript.py"}],
zipfile=None,
)
It creates a 'dist' folder, with the executable, a win9x executable, and the gfx and data folders next to the executable. However, when I run it it points me to a log which reads:
Traceback (most recent call last):
File "MyScript.py", line 16, in
File "zipextimporter.pyo", line 82, in load_module
File "psyco__init__.pyo", line 64, in
WindowsError: [Error 3] The system cannot find the path specified: 'C:\Documents and Settings\Keelx\Desktop\MyScriptFolder\dist\MyScript.exe\psyco\_psyco.pyd'
It would seem that the psyco module is not being put into the executable. I've been searching, and I haven't found a working solution to get py2exe to copy psyco over.
And please refrain from posting solutions along the lines of 'don't use py2exe'.
Thank you in advance whomever can help me out here.
Hunting down py2exe errors appears to be an art to me.
That said, I will at least offer something to try.
I py2exe'ed a psyco enabled python script and tossed it in the includes part of the setup.
Thats the only part that looks different between your setup and my old one.
options = {'py2exe': {'packages': [ 'IPython'],
'includes': ["psyco"],
}
}
Also I was never able to enable optimize. It always caused random errors. Best to leave that one off in my experience. I think it was matplotlib that caused those errors.
Hope this helps,
Cheers,

Categories