8000 Merge pull request #11 from topleft/chap10 · coderwxy/book1-exercises@590e6a0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 590e6a0

Browse files
committed
Merge pull request realpython#11 from topleft/chap10
changed paths, updated paths in solution files, reviewed solutions
2 parents 1c322a5 + 9b58aa5 commit 590e6a0

31 files changed

+415
-0
lines changed
Loading
Loading
Loading
Loading
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hi mom
Loading
Loading
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Hi there.
2+
This is a simple text file.
3+
If you can read me, congratulations!
Loading
Loading
Loading
Loading
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hi mom
Loading
Loading
Loading
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Person,Favorite pastime
2+
Fezzik,Fighting
3+
Westley,Winning
4+
Inigo Montoya,Sword fighting
5+
Buttercup,Complaining
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This is the first line
2+
The second line is longer
3+
Hippopotamus
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
LLCoolDave,23
2+
LLCoolDave,27
3+
red,12
4+
LLCoolDave,26
5+
tom123,26
6+
O_O,7
7+
Misha46,24
8+
O_O,14
9+
Empiro,18
10+
Empiro,18
11+
MaxxT,25
12+
L33tH4x,42
13+
Misha46,25
14+
johnsmith,30
15+
Empiro,23
16+
O_O,22
17+
MaxxT,25
18+
Misha46,24
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
First name Last name Reward
2+
Charlie Bucket golden ticket, chocolate factory
3+
Veruca Salt squirrel revolution
4+
Violet Beauregarde fruit chew
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
First name,Last name,Reward
2+
Charlie,Bucket,"golden ticket, chocolate factory"
3+
Veruca,Salt,squirrel revolution
4+
Violet,Beauregarde,fruit chew

refactor/chp10/solutions/10-1.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# 10.1 review exercises
2+
3+
4+
'''
5+
In order to run correctly, this script first needs to
6+
be placed in the Chapter 10 "practice_files" folder.
7+
(File paths are covered in section 10.2)
8+
'''
9+
10+
# Read a text file by looping over individual lines
11+
my_poem = open("poem.txt", "r")
12+
for line in my_poem.readlines():
13+
# Replace automatic line break at end of line;
14+
# file already contains newline characters
15+
print(line,)
16+
my_poem.close()
17+
18+
# Print some blank lines to separate the two examples
19+
print("\n\n")
20+
21+
# Use "with" to automatically close a file when finished
22+
with open("poem.txt", "r") as my_poem:
23+
for line in my_poem.readlines():
24+
print(line,)
25+
26+
# Write the contents of one file into another, line-by-line
27+
poem_in = open("poem.txt", "r")
28+
poem_out = open("output.txt", "w")
29+
for line in poem_in.readlines():
30+
poem_out.write(line)
31+
poem_in.close()
32+
poem_out.close()
33+
34+
# Repeat the previous exercise using the "with" keyword
35+
# (This will overwrite the previous output file.)
36+
with open("poem.txt", "r") as poem_in, open("output.txt", "w") as poem_out:
37+
for line in poem_in.readlines():
38+
poem_out.write(line)
39+
40+
41+
# Append a new line to the end of "output.txt"
42+
# (Need to start on a new line, so add "\n" to the beginning.)
43+
with open("output.txt", "a") as poem_append:
44+
poem_append.write("\nThus ends the haiku.")

refactor/chp10/solutions/10-2.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# 10.2 review exercises
2+
3+
4+
# Initial setup
5+
import os
6+
import glob
7+
# This path may need to be changed depending on your setup
8+
path = "C:/Real Python/refactor/chp10/practice_files/images"
9+
10+
11+
# Display the full paths of all files and folders in the main "images" folder
12+
print('Full contents of "images" folder:')
13+
for file_name in os.listdir(path):
14+
print(os.path.join(path, file_name))
15+
16+
# Display the full paths of any PNG files in the "images" folder
17+
file_matches = os.path.join(path, "*.png")
18+
print('All PNG files in "images" folder:')
19+
for file_name in glob.glob(file_matches):
20+
print(file_name)
21+
22+
# Change all PNGs to JPGs in the "images" folder and its subfolders
23+
# Could use indexing to get the file extension, but try using os.path.splitext()
24+
for current_folder, subfolders, file_names in os.walk(path):
25+
for file_name in file_names:
26+
file_path = os.path.join(current_folder, file_name)
27+
file_tuple = os.path.splitext(file_path) # split into (path, extension)
28+
if file_tuple[1].lower() == ".png": # check if extension is PNG
29+
pass # os.rename(file_path, file_tuple[0] + ".jpg")
30+
31+
# Check that the two files have been converted to JPGs successfully
32+
print(os.path.exists(os.path.join(path, "png file - not a gif.jpg")))
33+
print(os.path.exists(os.path.join(path, "additional files/one last image.jpg")))

refactor/chp10/solutions/10-3.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# 10.3 review exercises
2+
3+
4+
# Initial setup
5+
import os
6+
import csv
7+
# This path may need to be changed depending on your setup
8+
path = "C:/Real Python/refactor/chp10/practice_files"
9+
10+
11+
# Read in a CSV and display each row except the header row
12+
# Append a third column and write out the resulting CSV with a new header
13+
in_file_path = os.path.join(path, "pastimes.csv")
14+
out_file_path = os.path.join(path, "Output/categorized pastimes.csv")
15+
with open(in_file_path, "rb") as inFile, open(out_file_path, "wb") as outFile:
16+
csv_reader = csv.reader(inFile)
17+
csv_writer = csv.writer(outFile)
18+
19+
# skip header row and write a new output header row
20+
csv_reader.next()
21+
csv_writer.writerow(["Name", "Favorite Pastime", "Type of pastime"])
22+
23+
for row in csv_reader:
24+
print row
25+
# Check if "Favorite Pastime" includes "fighting"
26+
if row[1].lower().find("fighting") != -1:
27+
row.append("Combat")
28+
else:
29+
row.append("Other")
30+
# Add the new row to the output
31+
csv_writer.writerow(row)

refactor/chp10/solutions/csv_split.py

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import sys
2+
import os
3+
import csv
4+
import argparse
5+
6+
"""
7+
8+
Splits a CSV file into multiple pieces based on command line arguments.
9+
10+
Arguments:
11+
12+
`-h`: help file of usage of the script
13+
`-i`: input file name
14+
`-o`: output file name
15+
`-r`: row limit to split
16+
17+
Default settings:
18+
19+
`output_path` is the current directory
20+
headers are displayed on each split file
21+
the default delimeter is a comma
22+
23+
Example usage:
24+
25+
```
26+
# split csv by every 100 rows
27+
>> python csv_split.py -i input.csv -o output -r 100
28+
```
29+
30+
"""
31+
32+
33+
def get_arguments():
34+
"""Grab user supplied arguments using the argparse library."""
35+
36+
# Use arparse to get command line arguments
37+
parser = argparse.ArgumentParser()
38+
parser.add_argument("-i", "--input_file", required=True,
39+
help="csv input file (with extension)", type=str)
40+
parser.add_argument("-o", "--output_file", required=True,
41+
help="csv output file (without extension)", type=str)
42+
parser.add_argument("-r", "--row_limit", required=True,
43+
help="row limit to split csv at", type=int)
44+
args = parser.parse_args()
45+
46+
# Check if the input_file exits
47+
is_valid_file(parser, args.input_file)
48+
49+
# Check if the input_file is valid
50+
is_valid_csv(parser, args.input_file, args.row_limit)
51+
52+
return args.input_file, args.output_file, args.row_limit
53+
54+
55+
def is_valid_file(parser, file_name):
56+
"""Ensure that the input_file exists."""
57+
if not os.path.exists(file_name):
58+
parser.error("The file '{}' does not exist!".format(file_name))
59+
sys.exit(1)
60+
61+
62+
def is_valid_csv(parser, file_name, row_limit):
63+
"""
64+
Ensure that the # of rows in the input_file
65+
is greater than the row_limit.
66+
"""
67+
row_count = 0
68+
for row in csv.reader(open(file_name)):
69+
row_count += 1
70+
# Note: You could also use a generator expression
71+
# and the sum() function to count the rows:
72+
# row_count = sum(1 for row in csv.reader(open(file_name)))
73+
if row_limit > row_count:
74+
parser.error(
75+
"The 'row_count' of '{}' is > the number of rows in '{}'!"
76+
.format(row_limit, file_name)
77+
)
78+
sys.exit(1)
79+
80+
81+
def parse_file(arguments):
82+
"""
83+
Splits the CSV into multiple files or chunks based on the row_limit.
84+
Then create new CSV files.
85+
"""
86+
input_file = arguments[0]
87+
output_file = arguments[1]
88+
row_limit = arguments[2]
89+
output_path = '.' # Current directory
90+
91+
# Read CSV, split into list of lists
92+
with open(input_file, 'r') as input_csv:
93+
datareader = csv.reader(input_csv)
94+
all_rows = []
95+
for row in datareader:
96+
all_rows.append(row)
97+
98+
# Remove header
99+
header = all_rows.pop(0)
100+
101+
# Split list of list into chunks
102+
current_chunk = 1
103+
for i in range(0, len(all_rows), row_limit): # Loop through list
104+
chunk = all_rows[i:i + row_limit] # Create single chunk
105+
106+
current_output = os.path.join( # Create new output file
107+
output_path,
108+
"{}-{}.csv".format(output_file, current_chunk)
109+
)
110+
111+
# Add header
112+
chunk.insert(0, header)
113+
114+
# Write chunk to output file
115+
with open(current_output, 'w') as output_csv:
116+
writer = csv.writer(output_csv)
117+
writer = writer.writerows(chunk)
118+
119+
# Output info
120+
print()
121+
print("Chunk # {}:".format(current_chunk))
122+
print("Filepath: {}".format(current_output))
123+
print("# of rows: {}".format(len(chunk)))
124+
125+
# Create new chunk
126+
current_chunk += 1
127+
128+
129+
if __name__ == "__main__":
130+
arguments = get_arguments()
131+
parse_file(arguments)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# 10.3 high_scores.py
2+
# Read in CSV data containing names and scores; display a high score list
3+
4+
import csv
5+
import os
6+
my_path = "C:/Real Python/refactor/chp10/practice_files"
7+
8+
high_scores_dict = {}
9+
with open(os.path.join(my_path, "scores.csv"), "rb") as myFile:
10+
my_file_reader = csv.reader(myFile)
11+
for name, score in my_file_reader: # get each name/score pair
12+
score = int(score) # convert string score to integer
13+
if name in high_scores_dict: # already had an entry for that name
14+
if score > high_scores_dict[name]: # new score is higher
15+
high_scores_dict[name] = score
16+
else: # haven't seen this name yet; add it to dictionary
17+
high_scores_dict[name] = score
18+
19+
for name in sorted(high_scores_dict):
20+
print name, high_scores_dict[name]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# 10.2 remove_files.py
2+
# Remove JPG files from multiple folders based on file size
3+
4+
import os
5+
6+
path = "C:/Real Python/refactor/chp10/practice_files/little pics"
7+
for current_folder, subfolders, file_names in os.walk(path):
8+
for file_name in file_names:
9+
full_path = os.path.join(current_folder, file_name)
10+
# check if file is a JPG
11+
check_JPG = file_name.lower().endswith(".jpg")
12+
# check if size is less than 2Kb
13+
check_size = os.path.getsize(full_path) < 2000
14+
if check_JPG and check_size: # both conditions must be True
15+
print 'Deleting "{}"...'.format(file_name)
16+
os.remove(full_path)

0 commit comments

Comments
 (0)
0