Building a Python Application w/ GUI

The lesson learned in this was how much time goes into creating an effective GUI. I think that many of us take our day to day GUI’s for granted. The project was to create a more effective application to use with ElementTree, which is an additional library in Python to use for creating and parsing XML. The reason for the XML was that the XML was used for configuration file of a JAR based application.

First you have to start with:

#Tkinter calls for GUI
from Tkinter import *
import ttk

As the comment states this will call the Tkinter application. In Python 2.7 you must use CAPS Tkinter vs. Python 3.5 you use tkinter.

Everything is based into a root or main loop. This allows the application to run until the user quits, or the program is set to move on.

#Root window
root = Tk()
mainloop()
root.mainloop()

Inside of this is where your GUI will go. There are a ton of different ways to call for user input, checkbox, lists, text fields, etc. I choose to go with 1. Text Field, 2. Listbox and 3. Button for the user to run the program.

Most of the original program was a script that was running in standard Terminal. Previous to the GUI that application would ask the standard set of questions required for my variables.

while loop:  ## While loop which will keep going until loop = False
    print_menu()
    choice = input("Options 1-4 set the configuration of the report, option 5 runs the report: ")


    if choice == 1:
        print "Meaningful Use Stage 1 selected: "
        meaningfulUseStage="STAGE_1"
        periodYear = raw_input('What year is this report for?      Ex. 2012-2014')
    elif choice == 2:
        print "Meaningful Use Modified Scheduled Stage 1 selected: "
        meaningfulUseStage = "MODIFIED_SCHEDULED_STAGE_1"
        periodYear = "2015"
    elif choice == 3:
        print "Meaningful Use Stage 2 selected: "
        meaningfulUseStage = "STAGE_2"
        periodYear = "2014"
    elif choice == 4:
        print "Meaningful Use Modified Scheduled Stage 2 selected: "
        meaningfulUseStage = "MODIFIED_SCHEDULED_STAGE_2"
        periodYear = raw_input('What year is this report for?      Ex. 2015-2016')
    elif choice == 5:
        print "Running report: "
        ## You can add your code or functions here
        loop = False  # This will make the while loop to end as not value of loop is set to False
    else:


        raw_input("Wrong option selection. Enter any key to try again..")

This was much more simple since it did not require as many entries to accomplish the same goal. However, in the interest of the end users the GUI was a requirement.

This is the code for the Tkinter calls for a similar part of it. It does however, not contain the def and classes.

#Label for meaningfulUseStage list
providerIdLabel = Label(root, text="Please select a Meaningful Use Stage: ")
providerIdLabel.pack()
#meaningfulUseStage list selection
meaningfulUseStageList = Listbox(root, selectmode=SINGLE, height=4, width=30)
meaningfulUseStageList.pack()
for item1 in ["STAGE_1", "MODIFIED_SCHEDULED_STAGE_1", "STAGE_2", "MODIFIED_SCHEDULED_STAGE_2"]:
    meaningfulUseStageList.insert(END, item1)
    meaningfulUseStage = meaningfulUseStageList.curselection()

#Label for  periodYear
periodYearLabel = Label(root, text="Please the reporting year: ")
periodYearLabel.pack()
#periodYear list selection
periodYearList = Listbox(root, selectmode=SINGLE,height=5, width=30)
periodYearList.pack()
for item2 in ["2012", "2013", "2014", "2015", "2016"]:
    periodYearList.insert(END, item2)
    periodYear = periodYearList.curselection()

It is hard to say that it is inefficient as much as it was just more difficult since I was up to this point unfamiliar with Tkinter.

Some of the most common functions were:

Label() – Used to put a label, does not accept user input.

Listbox() – Structured user input, that can accept multiple selections.

Entry() – Text field that accepts user input.

Checkbox() – Check box that takes input in a binary function (on or off), the selection and lack thereof can be set to different tasks.

The tricky part of this was that some of the functions did not all behave in the same fashion. For example, calling Entry() and getting a str from the user input, was much less complex that getting the input from Listbox() or Checkbox(). The args were different and there is additional syntax. The benefit, however of using a more structured approach with Listbox() and Checkbox() is that the user cannot introduce variables that you haven’t already accounted for.

*More to follow

 

Advertisements
Building a Python Application w/ GUI

Using parallel to multi thread scripts

Traditional awk, sed or grep commends do not multi thread by default. Multi Threading a task on a large data set can improve the time up to 50%.

For additional information this package: http://www.gnu.org/software/parallel/

Dependencies: 

Debian 

sudo  apt-get install parallel

CentOS 6

wget http://download.opensuse.org/repositories/home:/tange/CentOS_CentOS-6/home:tange.repo

yum install parallel

Some use cases:
You want to find a string in text:
cat ./logs.csv | parallel  awk ‘/string/’ > ./stringoutput.csv

This parallel contains no additional functionality.

Lets say that you want to add the ability to break the file up into block sizes. After adding –block and size of block (ex. 100M, 10M, etc) you must add –pipe

cat ./logs.csv | parallel –block –pipe 100M  awk ‘/string/’ > ./stringoutput.csv

Since parallel is focused on maximizing the threads you can limit this by using: –jobs

By default –jobs is the same as the number of CPU cores. Arguments such as:

cat ./logs.csv | parallel –jobs 1 –pipe 100M  awk ‘/string/’ > ./stringoutput.csv

This will limit job to single CPU thread.

Summary:

parallel is very powerful addition to scripts that require additional or focused resources.

Source

 

Using parallel to multi thread scripts

Structuring a script to return value based on options. (BASH)

Let’s say you want to write a script to return a value or statement based on user input. How would you accomplish this?

Write a scrip to pass a color, return a result based on the color.

My first attempt was through the use of users selection in a particular set of available options. For instance:

#!/bin/bash
OPTIONS=”Blue Green Red”
select opt in $OPTIONS; do
    if [ “$opt” = “Blue” ]; then
      echo The sky is blue.
      elif [ “$opt” = “Green” ]; then
       echo The grass is green.
      elif [ “$opt” = “Red” ]; then
echo Roses are red.
      else
       clear
       echo Not a valid option. Please choose the following above. 
      fi

   done

 

When run this will show:
1) Blue
2) Green
3) Red 
If you input 1 and press Enter it will output:
      The sky is blue.
If you input 2 and press Enter it will output:
      The grass is green.
If you input 3 and press Enter it will output:
      Roses are red.
This is an IF ELSE statement that determines the output against the input.
Structuring a script to return value based on options. (BASH)

How to Telnet. *Old School

So lets say that you want to get a 200 request from a website such as: Sports.yahoo.com. How would you go about accomplishing that? What about Sports.Yahoo.com/NFL

The structure of the telnet request is:

telnet urlthatyouwanttoaccess.com portnumber (press enter)

GET (space) HTTP/1.1

host: urlthatyouwanttoaccess.com

  • telnet is the command, this is separated by a single space.
  • Then the URL of the site that you are making the telnet request to.
  • Followed by the port number, in most cases a website would be port 80.
  • Once you press Enter, you will put the request type.
  • In this instance GET (note the caps) then the request protocol HTTP/1.0 or 1.1. Then press Enter.
  • To finish the request type | host: URLyouwanttoaccess.com and select Enter.

NOTE: If you want to output the request into a text file, you can use: telnet urlthatyouwanttoaccess.com 80 > telnetoutput.txt | This will place the output of the request into a text file in the current directory.

 

 

How to Telnet. *Old School

List grouped and sorted by count unique IPs (BASH)

There are two possible solutions to this. My attempt was as follows.

cat ./listofip |awk ‘{print $1}|sort|uniq -c|sort -n|more

This rendered an adequate result, but my output was in reverse order and still contained ports.

      1 10.0.2.31:11999
      1 127.0.0.1:32000
      1 127.0.0.1:47016
      1 127.0.0.1:47642
      1 127.0.0.1:47644
      1 127.0.0.1:47662
      1 127.0.0.1:47664
      1 127.0.0.1:47666
      1 127.0.0.1:47710
      1 127.0.0.1:47716
      1 127.0.0.1:47768
      1 127.0.0.1:47779
      1 127.0.0.1:49418
      1 ::ffff:10.0.2.18:61617
      1 ::ffff:10.0.2.19:52039
      1 ::ffff:10.0.2.27:35840
      1 ::ffff:10.0.3.19:35024
      1 ::ffff:10.0.3.22:51753
      1 ::ffff:10.0.3.25:55746
      1 ::ffff:10.0.3.25:56089
      1 ::ffff:10.0.3.28:51756
      1 ::ffff:10.0.4.26:45995
      1 ::ffff:127.0.0.1:3306
      1 ::ffff:127.0.0.1:42719
      1 ::ffff:52.0.22.114:55340
      2 127.0.0.1:8009
      8 10.0.2.31:3306
My second attempt was:
cat ./listofip | awk ‘ $0 ~ /^(::ffff:|[0-9|])/ { gsub(“::ffff:”,””,$0); print $0}’ | cut -d: -f1 | sort | uniq -c | sort -nr
This returned the result of:
    16 127.0.0.1
      9 10.0.2.31
      2 10.0.3.25
      1 52.0.22.114
      1 10.0.4.26
      1 10.0.3.28
      1 10.0.3.22
      1 10.0.3.19
      1 10.0.2.27
      1 10.0.2.19
      1 10.0.2.18
However, I could have written this in a shorter way.
awk -F: ‘{print $(NF-1)}’ /tmp/foo | sort | uniq -c | sort -rn
Which would have returned the same result, but required less functions.
List grouped and sorted by count unique IPs (BASH)