Intro
I mostly transitioned from perl to python programming. I resisted for the longest time, but now I would never go back. I realized something. I was never really good at Perl. What I was good at were the regular expressions. So Perl for me was just a framework to write RegExes. But Perl code looks ugly with all those semicolons. Python is neater and therefore more legible at a glance. Python also has more libraries to pick from. Data structures in Perl were just plain ugly. I never mastered the syntax. I think I got it now in Python, which is a huge timesaver – I don’t have to hit the books every time I have a complex data structure.
I will probably find these tips useful and will improve upon them as I find better ways to do things. It’s mostly for my own reference, but maybe someone else will find them handy. I use maybe 5% of python? As I need additional things I’ll throw thm in here.
What is this object?
Say you have an object <obj> and want to know what type it is because you’re a little lost. Do:
print(<obj>.__class__)
Check if this key exists in this dict
if “model” in thisdict:
Remove key from dict
if “model” in thisdict: del thisdict[“model”]
Copy (assign) one dict to another
Do not use dict2 = dict1! That is accepted, syntactically, but won’t work as you expect. Instead do this:
dict2 = dict1.copy()
Multiple assignments in on line
a,b,c = “hi”,23,”there”
Key and value from a single line
for itemid,val in itemvals.items():
Formatting
I guess it is pretty common to use a space-based (not tab) indent of four spaces for each subsequent code block.
Initializing lists and dicts
alist = []
adict = {}
Test for an empty list or empty dict
if not alist: print(“empty list”)
if not adict: print(“the dict adict is empty”)
Length of a list
len(alist)
Merge two lists together
for elmnt in list2: list1.append(elmnt)
Address first/last element in a list
alist[0] # first element
alist[-1] # last element
First/Last two characters in a string
astring[:2]
astring[-2:]
Conditional operators
if a == b: print(“equals”)
if re.search(r’eq’,a):
do something
elif re.search(r’newstring’,a):
do something else
else:
etc.
Ternary operator
I don’t think is well-developed in Python and shouldn’t be used (my opinion).
++ operator? Doesn’t exist. += and its ilk does, however.
Boolean variables + multiple assignment example
a, b=True, False
if a==b: print(“equals”)
if a: print(“a is true”)
Reduce number of lines in the program
for n in range(12): colors[n] = ‘red’
if not mykey in mydict: mydict[mykey] = []
Printing stuff while developing
print(“mydict”,mydict,flush=True)
Python figures it out how to print your object, whatever type it is, which is cool. That flush=True is needed if you want to see our output which you’ve redirected to a file right away! Otherwise it gets buffered.
Reading and writing files – prettyify.py
import requests, json, sys, os
import sys,json
from pathlib import Path
aql_file = sys.argv[1]
aql_path = Path(aql_file)
json_file = str(aql_path.with_suffix('.json'))
# Script path
dir_path = os.path.dirname(os.path.realpath(__file__))
dir_path_files = dir_path + "/files/"
# make ugly json file prettier
# this is kind of a different example, mixed in there
file = sys.argv[1]
f = open(file)
# return json obj as dict
fjson = json.load(f)
nicer = json.dumps(fjson,indent=4)
print(nicer,flush=True)
# back to original example
f = open(dir_path_files + json_file,'w+')
f.write(body)
f.close()
Reading in command-line arguments
See Reading and Writing files example.
Command line tips
The command line is your friend and should be used for little tests. Moreover, you can print an object without even a print statement.
>>>a =[1,’hi’,3]
>>>a
Going from byte object to string
s_b = b’string’
s = s_b.decode(‘utf-8’)
Test if object is a string
if type(thisobject) == str: print(“It is a string”)
Python as a calculator
I always used python command line as a calculator, even ebfore I knew the language syntax! It’s very handy.
>>> 5 + 6/23
Breaking out of a for loop
Use the continue statement after testing a condition to skip remaining block and continue onto next iteration. Use the break to completely skip out of this loop.
Executing shell commands
import os
os.system(“ls -l”)
But, to capture the output, you can use the subprocess package.
Generate (pseudo-)random numbers
import random
a = random.random()
Accessing environment variables
os.environ[‘ENV_TOKEN’]
Handling glob (wildcards) in your shell command
import glob
for query_results_file in glob.glob(os.path.join(dir_path_files,OSpattern)): print(“query_results_file”,query_results_file)
But, if you want the results in the same order as the shell gives, put a sorted() around that. Otherwise the results come out randomly.
JSON tips
Python is great for reading and writing JSON files.
# Load inventory file
with open(dir_path_files + inventory_file) as inventory_file:
inventory_json = json.load(inventory_file)
sitenoted={'gmtOffset':jdict["gmtOffset"],'timezoneId':jdict["timezoneId"]}
# update inventory with custom field Site Notes – put GMT
sitenote=json.dumps(sitenoted,indent=4)
print("sitenote",sitenote)
Convert a string which basically is in json format to a Python data structure
import json txt_d = json.loads(response.text)
Test for null in JSON value
You may see “mykey”:null in your json values. How to test for that?
if my_dict[mykey] == None: continue
RegExes
Although supported in Python, seems kind of ugly. Many RegExes will need to prefaced with r (raw), or else you’ll get yourself into trouble, as in
import re
r'[a-z]{4}.\s*\w(abc|def)’
if re.search(‘EGW-‘,locale): continue
b = re.sub(‘ ‘,’-‘,locale)
b = re.split(r’\s’,’a b c d e f’)
Minimalist URL example
import urllib.request
urllib.request.urlopen(‘https://drjohnstechtalk.com/’).read()
Function arguments: are they passed by reference or by value?
By reference for complex objects like a dict (not sure about a list), but by value for a simple object like a Boolean! I got burned by this. I wanted a Boolean to persist across a function call. In the end I simple stuffed it into a dict! And that worked. But python doesn’t use that terminology. But it means you can pass your complex data structure, say a list of dicts of dicts, start appending to the list in your function, and the calling program has access to the additional members.
Excel files
I’ve been using the package openpyxl quite successfully to read and write Excel files but I see that pandas also has built-in functions to read spreadsheets.
Math
numpy seems to be the go-to package.
Can a keyword be a variable?
Yes. Here’s an example.
timeunit = ‘days’
numbr = 3
datetime.now() + timedelta(**{timeunit: numbr})
Python and self-signed certificates, or certificates issued by private CAs
I updated this blog article to help address that: Adding private root CAs in Redhat or SLES or Debian.
Write it with style
Use flake8 to see if your python program conforms to the best practice style. In CentOS I installed flake8 using pip while in Debian linux I installed it using apt-get install flake8.
Can I modify a Python script while its running?
Sure. No worries. It is safe to do so.
Create virtual environment for portability
I like to call my virtual environment venv.
virtualenv venv
Use this virtual environment
source ./venv/bin/activate
List all the packages in this virtual environment
Good portable development style would have you install the minimal set of packages in your virtual environment and then build a requirements.txt file:
pip3 freeze > requirements.txt
Leave this virtual environment
deactivate
Conclusion
I’ve written down some of my favorite tips for using python effectively.