LBYL vs EAFP

So, it’s been almost a year since I’ve posted something, and it’s been a busy year.

ERATE twice, pushing my CCIE recert to the edge of losing it (23 days left in suspension when I passed), getting married to my best friend (Halloween if anyone is wondering), and yes still working to learn python.

One of my personal projects was a script that used FFMPEG to convert media files to X.265.
While I was doing this, I stumbled upon what appears to be a common…question? oddity? something anyway.

Look Before You Leap LBYL or Easier to Ask For Permission EAFP

Basically when you are getting ready to do something:
Do you check if a value/key is there first?
or
Do you just “try” and if it fails catch an “except” and do something else?

In my case, I was attempting to write a script that could take the base directory having the files in it directly, like:
/Movies/
or have the file in a folder like:
/TV/Constantine/
And expect to have “Season” folders

As I’m lazy, I don’t want to have two scripts to do this, or to have to modify code each time.

So the first thing I did was use split to create a list.(ok technically the second thing I did, as the first thing was to create a list of files that matched my criteria)

with open(found, 'rt') as shows:
for row in shows:
line = row.rstrip().split('/')

When the base is /Movies we only have line[0] = filename
When the base is /TV/Constantine/ we have line[0] = Season and line[1] = filename

Now that I have a list, I tried to check if element [1] exists

if len(line[1]) >= 1:

and if there was something there, it worked!!
if there isn’t anything there, it errors out….

Really? There is an else statement following…if it wasn’t true why didn’t it continue to the else?
after trying different things to make this work, and not being able too, I found a reference to

Once I did this:

try:
if len(line[1]) >= 1:

It actually worked!

Now, I still don’t fully understand why LBYL didn’t work, but a lot of code I found while searching for an answer seemed to follow EAFP using try/except method.

More Python goodness

Still working on learning how to use Python to do scripting and automation. I did hit a bit of a roadblock with one project as the documentation on the site had embedded links to some examples…and the links were broken. Kept trying to figure out how to get to them, tried different ways of creating the link from where the main documentation was at, nothing worked. Months of trying this off and on, and then I struck gold!! “Why don’t I just ask for them?” yeah, seems obvious and it should have been, but I had to do some digging to find an email address to send the question to. But wooo!! I finally have the schemas, so I’ll get back to that project eventually.

On to another subject kind of…

A friend of mine, posted some stuff a while back. Good resources to start learning with, so go take a look at Ashley McNamara’s blog.

And I’ve been working (trying too anyway) my way through the stuff on Cisco DevNet as well. Nice thing here as you go through the courses, they have links to their Cisco DevNet Github so you can clone the repo and have the scripts they use already. You’re always free to create your own, but if you are just using their sandbox server, they work great!

Token…anyone seen my token

Trying to learn python and scripting has lead me to using API calls. While some things are just fun to play with like FoaaS, others can be really useful.

Generally for a call to work, you need to have an API key. Some places may give you your API key, and some places you may need to generate one.

Generating one wasn’t really the problem, for the most part I was able to use my Google-Fu and find a ton of different ways to do this. Since I’m doing this with Python I decided to use requests for the OAuth2 piece. If you don’t have it already “pip install requests” will grab it for you.

What I was playing with a simple “Hello API” and the examples they had were all using curl.

Step 1 – Get your access token
curl -s -k -H “Content-Type: application/x-www-form-urlencoded” -X POST -d “client_id=” -d “client_secret=” -d “grant_type=client_credentials”

So reading man page/googling the options I was able to find out that “curl -H” is building the header and -d is the payload/data.

The easy part converting the curl to Python:

#! /usr/bin/env python

import requests

payload = {
    'grant_type': 'client_credentials',
    'client_id': "client ID",
    'client_secret': "client secret"
}

headers={
	'content-type': "application/x-www-form-urlencoded"
}

#-----------------------------------------------------------
	#Get access Token

r=requests.post("authentication url", data=payload, headers=headers)
print(r.text)

By doing this, I was able to login and generate the my access token and print it. So now I know what my token is.

Step 2 – Make the call

curl -s -k -H “Accept: application/json” -H “Authorization: Bearer

So I have my token, but how do I use it. Again my example was using curl, and yes it worked…but I wanted to do this as a single script. Google to the rescue!!

Since the response is coming back in json, I should be able to do something with that information, but how? Requests has a built in json decoder. By adding the “r.json()” after the post, I was able to cram the response into an object.

from pprint import pprint

r=requests.post("auth url", data=payload, headers=headers)
d=r.json()

pprint(r.json())

pprint gave me:

{u’access_token’: u’token’,
u’expires_in’: 3599,
u’token_type’: u’Bearer’}

Further digging/swearing/searching/swearing and I figured out how to take that data and make it a variable:

r=requests.post("https://cloudsso.cisco.com/as/token.oauth2", data=payload, headers=headers)
d=r.json()

#pprint(r.json())
mytok=d['access_token']

Now I have my token stored as a usable variable for Step 2. It took me a bit to figure out what the header configuration needed to look like. As you see from the curl example, I needed the Authorization to be + and at first I was trying to push both the “Bearer” and “Token” as a variable, but why? For this usage the token_type will always “Bearer”.

headers={
	'accept': "application/json",
	'authorization': "Bearer " + mytok
}

h=requests.get("hello api url", headers=headers)
print(h.text)

SUCCESS!!! Once I put all the pieces together, I can call the script and it does the login, grabs the token, stores the token as a variable, then uses it for the final call.

#! /usr/bin/env python

import requests
from pprint import pprint

payload = {
    'grant_type': 'client_credentials',
    'client_id': "client ID",
    'client_secret': "client secret"
}

headers={
	'content-type': "application/x-www-form-urlencoded"
}

#-----------------------------------------------------------
	#Get access Token and store in json

r=requests.post("oauth url", data=payload, headers=headers)
d=r.json()

#pprint(r.json())
mytok=d['access_token']

#------------------------------------------------------------
	# Use json data to fill token information
headers={
	'accept': "application/json",
	'authorization': "Bearer " + mytok
}

h=requests.get("hello api url", headers=headers)
print(h.text)

{“response”:”Hello World”}

Scripting with Multiple Machines

I’ve been trying to learn python and scripting in general. If I can make certain parts of my job easier by writing a script why not?

With that I’ve taken to doing some customization on my environment.

    Using Zsh instead of bash (pulled from Homebrew)
    oh-my-zsh (customization of zsh)
    Homebrew (package manager, can install all kinds of fun things)
    Pathogen (runtime for VIM)
    help from friends! Tony Mattke, Teren Bryson and others.
    DropBox
    GitHub of course!

The problem I was having was how to keep my customization and scripts in sync between my work machine and my personal machine. The answer I found, well one answer that works for me, is DropBox! Though you could probably use any cloud storage provider you wanted. I created a folder in my DropBox called “sync” and I symlink the files/folders I want to keep in sync on both machines into it.

Now, when I make a change to my .vimrc, zsh custom folder, or basically anything else I have symlinked, the change gets reflected to the other machine.

To ARGV or to To Variable, is it really a question?

Ok, so it’s not the best title ever, considering, but what the heck.

So still working through the Python lessons. So far it doesn’t seem too different from what I used to do with a shell/bash script ( I inherited some and learned what they did. Then created some new ones based on them). Though the ‘language’ does seem to be a bit easier, and I see how it might be easier to accomplish some things better.

That being said, most of the lessons so far, are calling for argv values, for lack of a better term. With this you call the script with arguments after the file name:

ex17.py old.txt new.txt

ex17

theirs

So that does seem to work, so long as the person who calls the script knows what they are supposed to do.

Personally I prefer something more like this:

ex17a

mine

Yes it is more lines of code, but to me at least, it seems more user-friendly. I could have anyone call my script and it asks them for the file names vs expecting them to know what they are supposed to do.

Python Day 1

So trying to learn some python. I had a couple of people recommend this course.

So I started to run through it on Friday. First two lessons were not that bad. Basic “print” statements to start followed by “comments/#” usage.

So far so good right? In comes lesson three, math with python. Most of the basic functions were easy to pick up. Multiplication, division, addition, subtraction and of course the proper order of operations. It also goes into > greater than, >= greater than or equal to, < less than, <= less than or equal to, and finally % percentage/remainder. Or at least I think it’s supposed to be remainder.

It is this final piece that has been kicking my butt. So I get that the modulus (%) is for remainder, I can’t figure out how it works.
The formula for the exercise is ” 100 – 25 * 3 % 4″ the answer is 97.

So I’m still trying to figure out how this works before I move on. Of any of you out there can point out a good explanation feel free to let me know.

Or once I figure it out I’ll update.

 

Update

 

Ok, so with the help of a coworker it looks like I’ve figured this out.  So the “%” means divide by following number, but use the remainder for the next piece of the equation.

So what that means for the above equation:

100 – 25 * 3 % 4

100 – 75 % 4 ( which means 75 / 4 which is 18.75, but not using floating points yet, so it’s 18 remainder of 3)

100 – 3

97

 

And I’m sure my Algebra I teacher would be happy I showed my work…