Introduction to Python

davidbpython.com




Projects, Session 6



PLEASE REMEMBER:

  1. re-read the assignment before submitting
  2. go through the checklist including the tests
  3. make sure your notations are as specified in the homework instructions

All requirements are detailed in the homework instructions document.

Careless omissions will result in reductions to your solution grade.

 

NOTE ON OPENING FILES

If the file you want to open is in the same directory as the script you're executing, use the filename alone:
fh = open('filename.txt')
If the file you want to open is in the parent directory from the script you're executing, use the filename with ../:
fh = open('../filename.txt')
If the file you want to open is in a child directory from the script you're executing, use the filename with the child directory name prepended:
fh = open('<childdir>/filename.txt')

(Replace <childdir> with the name of the child directory.)

 
6.1 Notes typing assignment. Please write out this week's transcription notes. The notes are displayed as an image named transcription in each week's project files folder.

This does not need to be in a Python program - you can use a simple text file.

 
6.2 Command Line Exercises.

As usual, returned solutions will lose points. It is recommended to confirm (through testing) that your answer is correct before submitting to ensure that you will receive credit. First, determine where you have placed your python_data folder. You may have chosen to leave it in Downloads, or moved it to your Desktop folder or in your home directory, or to another folder of your choosing. To find the directory from the command line, you must be able to know the relative path that leads from the home directory to your python_data directory. (My python_data directory is in my Downloads directory, and since this is in my home directory, the path is Downloads/python_data. If your folder is in Desktop, the relative path is Desktop/python_data.)

1. Open a Windows Explorer or Mac Finder window and find the python_data_ipy folder. As with previous sessions, this week's session_06_multis folder contains the dir1 folder tree:
python_data_ipy
├── session_00_test_project
├── session_01_objects_types
├── session_02_funcs_condits_methods
├── session_03_strings_lists_files
├── session_04_containers_lists_sets
├── session_05_dictionaries
└── session_06_multis
    └── dir1
        ├── file1.txt
        ├── test1.py
        │
        ├── dir2a
        │   ├── file2a.txt
        │   ├── test2a.py
        │   │
        │   └── dir3a
        │       ├── file3a.txt
        │       ├── test3a.py
        │       │
        │       └── dir4
        │           ├── file4.txt
        │           └── test4.py
        └── dir2b
            ├── file2b.txt
            ├── test2b.py
            │
            └── dir3b
               ├── file3b.txt
               └── test3b.py

2. Please update the following files as specified:

test1.py:  update the argument to the open function so that it opens file file1.txt.
test3b.py:  update the argument to the open function so that it opens file file3b.txt.

3. Open your computer's command line program (on Windows it is called Anaconda Prompt; on the Mac it is Terminal). Please do not use PyCharm's Terminal tab for this assignment. (If you did not install Anaconda on Windows and so don't have the Anaconda Prompt, please email me.) 4. Now, in the same command line session, please perform the following actions in this order: A. Travel to dir3b B. Execute file test3b.py C. Travel back down to dir1 D. Execute file test1.py Please remember that executing (i.e., running) a file is not done using the open command; instead it is done with the python (Windows) or python3 (Mac) command. Note: please don't return to your home directory during the above journey - use '..' when you need to travel to a parent directory. 5. If you made a lot of mistakes in performing the above, please make note of the correct commands that you needed, then click the small 'x' at the top left tab of the Terminal window to close the Terminal, and then reopen it and start fresh using the correct commands (it's OK to make a few mistakes; your commands do not have to be perfect!). 6. Finally, please copy and paste your entire Terminal session into the homework submisssion window and submit.

 
6.3 Trap one known exception and one undiscovered exception. Take two inputs using two calls to input(), asking for integer values. Convert to int, then divide one value by the other.

If the values are valid integers and the division is successful, print the result as shown below, rounding any fractional values to 2 places. If the values are not valid integers, OR the division is unsuccessful (see below when attempting to divide by 0), print an error message. You'll use try/except block to trap the error. YOU MUST TRAP TWO POSSIBLE EXCEPTIONS (not necessarily more than one try: block) that could occur if user input is incorrect. The first is the exception raised by int() when converting the user's input to numbers. The second is the exception raised when dividing by 0. In order to see what exception is raised when you attempt to divide by 0, simply divide by 0 and allow the exception to occur. Python will respond with an exception that includes the exception type you must trap. YOU MUST TEST YOUR PROGRAM AS SHOWN BELOW. (User input is shown in each example.)

Sample program run:
please enter an int:  5
please enter an int:  3

5 / 3 = 1.67
Sample program run:
please enter an int:  5
please enter an int:  three

error:  both values must be whole numbers
Sample program run:
please enter an int:  5
please enter an int:  0

error:  second value cannot be 0

YOU MUST USE a try/except BLOCK to trap the above exceptions. YOU MUST NOT USE if! For extra excitement, use a single try: block to perform all of the possibly error operations (converting two values to int, division) and then use chained except: blocks to handle each of the two possible exceptions. See the slides for examples of chaining except: blocks.
HOMEWORK CHECKLIST: all points are required


    testing: you have run the program with the sample inputs as shown and are seeing the output exactly as shown (contact me if your output is different and you're unable to adjust to match)

    code does not make use of 'if' tests to detect user errors; instead, uses try/except to trap errors after they occur

    program does not use except: by itself, nor except Exception: as these trap any type of exception

    try: block surrounds only those lines that may raise exceptions; no other lines are included in the try: block

 
6.4 Write a program that reads a config from a multidimensional structure stored in JSON format, and print out its contents in a readable format.

Start with this code:

import json

fh = open('config.json')
conf = json.load(fh)

fh.close()
The config.json file looks like this:
[
  {
    "domain": "www.example1.com",
    "database": {
      "host": "localhost1",
      "port": 27017,
      "live": false,
      "last_read":  1677342217.673389
    },
    "plugins": [
       "plugin1",
       "eslint-plugin-plugin1",
       "plugin2",
       "plugin3"
    ]
  },
  {
    "domain": "www.example2.com",
    "database": {
      "host": "localhost2",
... continued ...

Your program will loop through and output this same data in a readable format.

Expected Output:
domain:  www.example1.com
db_host:  localhost1
db_port:  27017
plugins:
  plugin1
  eslint-plugin-plugin1
  plugin2
  plugin3


domain:  www.example2.com
db_host:  localhost2
db_port:  27017
plugins:
  plugin2
  eslint-plugin-plugin2


domain:  www.example3.com
db_host:  localhost3
db_port:  27017
plugins:
  plugin3
  eslint-plugin-plugin3

Note that the above example assumes that your script is in the same directory as config.json. If Python can't find your file, it may be because the relative path is incorrect. Please see "Filepaths for Locating Files" in the Session 3 Slides. Also keep in mind that we know the keys in each of these dicts. Therefore we don't need to (and should not) loop through the dicts. Instead, you must use hard-coded dictionary keys for this assignment. Special error note: if you get a JSONDecodeError this means that something is wrong with the json in the .json file, such as a missing quote or comma; this is similar to a SyntaxError in Python. This might happen if you open the .json file and then save it. To fix this problem, re-download the python_data_ipy folder and copy over the same .json file to replace the file in your project directory (i.e., your original copy of python_data_ipy) and try again - let me know if you can't resolve this issue. Also please note that you aren't required to notate the entire struct -- just show the first several characters to indicate that you know what the value is (a list of dicts).

HOMEWORK CHECKLIST: all points are required


    code does not subscript either of the lists -- since we don't necessarily know how many items are in either the plugins list or the overall list of dicts, we loop through them

    code does not loop through any of the dictionaries -- since we definitely know the names of keys, and since we don't want all of them, we can use a subscript with hard-coded keys

    code does not subscript the "plugins" list -- since we don't necessarily know how many items are in the list, we loop through it

    there are no extraneous comments or "testing" code lines

    program follows all recommendations in the "Code Quality" handout

 

EXTRA CREDIT / SUPPLEMENTARY

 
6.5 (Extra credit / supplementary.) Reading through FF_tiny.txt, build a dict of lists in which the key is the 4-digit year and the value is a list of Mkt-RF values (the 2nd column, or leftmost float values) for that year.

Brief discussion:

As you loop line by line through the file, the statement adding to the dict is this:
year_vals[year].append(mktrf)

where year is the 4-digit year from the line and mktrf is the Mkt-RF value (the 2nd column, or leftmost float value) from the line. However, as discussed, you will need to check the dict ahead of time to see if the ticker key is already there. If the year is new, set the key and value in the dict for that line to an empty list.

year_vals[year] = []

In building the dict, please avoid looping through the FILE more than once (you WILL NEED to loop through the dict once you've built it, in order to display the results). Please avoid using a separate list or set to hold any of the values. A dictionary of lists is all you need! This exercise helps you see how you can build a multidimensional structure.

By the end, your structure should look like this:
{ '1926': [0.09, 0.44],
  '1927': [0.97, 0.3, 0.0, 0.72],
  '1928': [0.43, 0.14, 0.71]       }

Please loop through the year keys, and print out the year and the values for that year.

Sample program run:
1926:  [0.09, 0.44]
1927:  [0.97, 0.3, 0.0, 0.72]
1928:  [0.43, 0.14, 0.71]

Note that if Python can't find your file, it may be because the relative path is incorrect. Please see "Filepaths for Locating Files" in the Session 3 Slides.
HOMEWORK CHECKLIST: all points are required


    there are no extraneous comments or "testing" code lines

    program follows all recommendations in the "Code Quality" handout

 
6.6 (Extra credit / supplementary.) Use the NOAA Weather API to access the weather forecast in Hamilton Heights, NYC (10031).
import requests
import json
response = requests.get('https://api.weather.gov/gridpoints/'
                        'OKX/33,39/forecast')

obj = json.loads(response.text)

Please note that sometimes the NOAA API is not available - if so, you must wait until it becomes available again.

You can use json to view a structure in a "pretty" (readable) format:
import json
print(json.dumps(obj, indent=4))

Without any prior information provided here, inspect the resulting data structure and extract the following information (your specific temp and time data will be different), presenting it as formatted below:

Saturday, 2019-03-23             # instead of Saturday may be 'Tonight', 'This Afternoon', etc.
18:00

Mostly sunny. High near 50, with temperatures falling to around 48 in the
afternoon.  Wind chill values as low as 23. Northwest wind 18 to 23 mph,
with gusts as high as 35 mph.

There are several forecasts in the data -- please select the earliest. To format the data as above, best is to use f'' strings. If you get an error mentioning SSL: CERTIFICATE_VERIFY_FAILED then please refer to discussion in the Session 3 slide deck involving requests -- the code needed to circumvent this error can be found there. Please note you do not need to include notations for this solution.

 
[pr]