Python: raise KeyError(key) from None

This:

#!/usr/bin/env python3
import os
testing = os.environ['testing']

will generate:

Traceback (most recent call last):
  File "./my.py", line 3, in <module>
    testing = os.environ['testing']
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/os.py", line 669, in __getitem__
    raise KeyError(key) from None
KeyError: 'testing'

if the environment variable does not exist.

 

Instead use:

testing = os.environ.get('testing', 'False')

which lets you set a default.

 

Install multiple versions of Python

 

Ignore the top link on Google which takes you a process of using pyenv. It’s not until you’ve spent several hours painstakingly following the instructions that you find out it’s for some shell I’ve never used called Fish.

Just do:

  1. brew install python2
  2. brew install python3
  3. then to use Python 2, use python2 and for Python 3, use python3

 


i.e. DON’T DO:

  1. use pyenv
  2. make sure brew is up to date: brew update && brew upgrade pyenv
  3. pyenv install 3.7.2
  4. pyenv install 2.7.14
  5. Set the global version with pyenv global 3.7.2
  6. Set local versions (e.g. for legacy projects) with pyenv local 2.7.14

 

Notes:

  • latest version of Python: https://www.python.org/downloads/
  • Blog post on pyenv: https://weknowinc.com/blog/running-multiple-python-versions-mac-osx

 

Problems:

ERROR: The Python zlib extension was not compiled. Missing the zlib?

brew install readline xz

did not work for me.

This worked though:

CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install -v 2.7.14

 

More:

https://github.com/pyenv/pyenv/wiki/common-build-problems

 

 

 

Python: how to concatenate strings when one is None

TLDR

Use: print "Some URL: %s" % (some_url)

rather than: print("Some URL " + some_url)

 

 

Try to print out a variable that’s actually None rather than a string, e.g. with

print("Some URL " + some_url)

will result in:

Traceback (most recent call last):
File "my-script.py", line 451, in 
lambda_handler(None, None)
File "my-script.py", line 442, in lambda_handler
print("Some URL: " + some_url)
TypeError: cannot concatenate 'str' and 'NoneType' objects

Python should not be so dogmatic.

Why Python sucks &#8211; why I hate Python: a Python rant

 

You can do:

print("Some URL: ")
print(some_url)

but that’s dodging the problem. It assumes that you’re aware of the potential bug before you code. Also, you end up with the text on two separate lines.

 

The solution is to use this syntax:

print "Some URL: %s" % (some_url)

 

 

 

 

 

Python: main

Breaking down the Python from https://github.com/jorgebastida/awslogs

It’s installed with:

pip install awslogs --ignore-installed six

 

Files are packaged using a setup.py file. E.g.

https://github.com/jorgebastida/awslogs/blob/master/setup.py

https://packaging.python.org/tutorials/packaging-projects/

 

Here’s a sample script (/usr/local/bin/awslogs – source code: https://github.com/jorgebastida/awslogs):

#!/usr/local/opt/python@2/bin/python2.7

# -*- coding: utf-8 -*-
import re
import sys

from awslogs.bin import main

if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

 

#!/usr/local/opt/python@2/bin/python2.7

Path to Python. No idea why there’s an @.

https://stackoverflow.com/questions/53482939/why-is-there-an-symbol-in-the-shebang-of-my-python-script

Side note: you should use a shebang like:

#!/usr/bin/env python3

https://stackoverflow.com/questions/6908143/should-i-put-shebang-in-python-scripts-and-what-form-should-it-take

 

 

# -*- coding: utf-8 -*-

Specifies the encoding.

https://stackoverflow.com/questions/4872007/where-does-this-come-from-coding-utf-8

 

import re
import sys

Imported as used later on. E.g. sys.argv[0]

 

from awslogs.bin import main

means: from the package awslogs.bin import the module main.

https://docs.python.org/2/tutorial/modules.html#more-on-modules

How does Python find these packages?

They’re in it’s path. E.g.

python
import sys
print '\n'.join(sys.path)

and

ls /usr/local/lib/python2.7/site-packages/awslogs*
/usr/local/lib/python2.7/site-packages/awslogs:
__init__.py    _version.py    bin.py         core.py        exceptions.py
__init__.pyc   _version.pyc   bin.pyc        core.pyc       exceptions.pyc

/usr/local/lib/python2.7/site-packages/awslogs-0.10.0.dist-info:
DESCRIPTION.rst  METADATA         WHEEL            metadata.json    top_level.txt
INSTALLER        RECORD           entry_points.txt pbr.json

What is this dist-info directory?

It’s created by Wheel – one of Python’s packaging formats. See: https://packaging.python.org/discussions/wheel-vs-egg/

and

the mainfunction is from awslogs/bin.py here:

/usr/local/lib/python2.7/site-packages/awslogs/bin.py

More on sys.path: https://leemendelowitz.github.io/blog/how-does-python-find-packages.html

 

if __name__ == '__main__':

If run from the command line (e.g. python this-file.py ) then __name__ will == '__main__'. Otherwise, if it’s been run as a module then __name__ will be the name of the module.

https://stackoverflow.com/questions/419163/what-does-if-name-main-do

 

sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])

https://stackoverflow.com/questions/53483812/what-does-this-line-do-sys-argv0-re-subr-script-pyw-exe-s

https://www.pythonforbeginners.com/system/python-sys-argv

 

sys.exit(main())

https://stackoverflow.com/questions/5280203/what-does-this-mean-exit-main

 

Python: getting rid of the ‘u’ symbol when outputting text

I find it really annoying that whenever Python prints a string it prints out a u when it’s Unicode.

When you copy and paste that stuff it retains it all. If you’re copying and pasting JSON you’re left with broken JSON. Here’s how to get rid of it:

data = json.dumps(d, ensure_ascii=False).decode('utf8')
print data

 

Python > Inspect an object

Use

print dir(<my object>)

where <my object> is your object name.

https://stackoverflow.com/questions/192109/is-there-a-built-in-function-to-print-all-the-current-properties-and-values-of-a?noredirect=1&lq=1

 

dirreturns the list of names in the current local scope.

https://docs.python.org/3/library/functions.html#dir

 

vars returns the __dict__attribute for a module, class or instance.

https://docs.python.org/3/library/functions.html#vars

 

__dict__ is a dictionary or other mapping object used to store an object’s writable attributes.

https://docs.python.org/3/library/stdtypes.html#object.__dict__