Problem with extended version of ex21

I’ve been trying to elaborate on ex21 - taking previous lessons into account.

Basically I want to make a script that calculates house dimensions and an saves it as a .txt file.

def surface(lenght, width):
    print(f"Calculating...\nlength: {lenght}m\nWidth: {width}m")
    return lenght * width

wall_height = int(input("How high is wall in meters?\n>>>"))
wall_length = int(input("How long is the lenght of the building?\n>>>"))
wall_width = int(input("How wide is the building?\n>>>"))

area = surface(wall_length, wall_width)
facade2 = surface(wall_width, wall_height)
facade3 = surface(wall_height, wall_length)

data_input = print(f"""Building area is: {area}m2
First facade is: {facade2}m2
Second faceade is: {facade3}m2
House size: """, facade2 * wall_length,"""m3
""")
print(data_input)

input("Do you want to put that into a document?\nif YES press RETURN  |  if NO press CTRL-C")
filename = input("What do you want to call your file?\n")
filename = print(f"{filename}.txt")

save_file = open(filename, 'w')
save_file.write(data_input)
save_file.close()

but i get this terminal error:
Traceback (most recent call last):
File “ex21_2.py”, line 24, in
save_file = open(filename, ‘w’)
TypeError: expected str, bytes or os.PathLike object, not NoneType

I don’t understand this as I guess everything i use as input is by definition a string?
or what am I missing?

My guess based on that error message is that you are trying to open a file that doesn’t exist. You captured the name of the file as your input, and then try to open it to write to, but there is no such file in your local directory.

A quick fix might be to open the file with:

open(filename, 'x')

This should open the file with exclusive creation unless it already exists (https://docs.python.org/3/library/functions.html#open)

Hi @gpkesly

The file does not exist. However I don’t know how familiar you are with the lessons in learn code the hard way, but in lesson 17 I did this:

from sys import argv
from os.path import exists

script, from_file, to_file = argv

print(f'copying from {from_file} to {to_file}')

in_file = open(from_file).read()
#indata = in_file.read()

print(f"""The input file:{len(in_file)} bytes.
Does the output file exist? {exists(to_file)}.
Ready, hit RETURN to continue, CTRL-C to abort.""")
input()

out_file = open(to_file, 'w')
out_file.write(in_file)

print("Alright, all done.")

out_file.close()
#when I reach the end of a script it automatically closes
#in_file.close()

Which creates the to_file if it does not exist.

I tried to change the ‘w’ to ‘x’, but I still get this error.

Traceback (most recent call last):
File “ex21_2.py”, line 24, in
save_file = open(filename, ‘x’)
TypeError: expected str, bytes or os.PathLike object, not NoneType

Ah OK. I had a decent look. There are a few issues here although I might not be understanding what you want to achieve.

  1. I don’t think you want the print statement before the multi-line string with lots of variables injected.
  2. Using ‘filename’ twice is confusing as its already declared. Again you do not need print here.
  3. Because you use ‘data_input’ in your file write, it expects a string. But you didn’t include {} around ‘facade2 * wall_length’ in the multi-line string, only commas, so you actually created a tuple.

I think this is similar to your goal:

def surface(length, width):
    print(f"Calculating...\nlength: {length}m\nWidth: {width}m")
    return length * width

wall_height = int(input("How high is wall in meters?\n>>>"))
wall_length = int(input("How long is the lenght of the building?\n>>>"))
wall_width = int(input("How wide is the building?\n>>>"))

area = surface(wall_length, wall_width)
facade2 = surface(wall_width, wall_height)
facade3 = surface(wall_height, wall_length)

data_input = f"""
Building area is: {area}m2
First facade is: {facade2}m2
Second faceade is: {facade3}m2
House size: {facade2 * wall_length}m3
"""

print(data_input)

input("Do you want to put that into a document?\nif YES press RETURN  |  if NO press CTRL-C")
name_file = input("What do you want to call your file?\n")
filename = f"{name_file}.txt"

save_file = open(filename, 'w')
save_file.write(data_input)
save_file.close()

In this code you have a spelling mistake on line 1 (lenght vs length), which causes some problems.

You also are doing this:

filename = input("What do you want to call your file?\n")
filename = print(f"{filename}.txt")

I think I’ve seen you or someone else do this thing of, “I have to print a string to format it and assign it.” But, you don’t and that causes your error here. To do what you want just do this:

filename = input("What do you want to call your file?\n")
filename = f"{filename}.txt"

Here’s where you are getting confused on that:

  1. The f"" will format a string and create a string. It has absolutely nothing to do with print at all. You could do that with a plain variable, other functions, anything. We call this “orthoginal” meaning the f"" is a piece that can be interchangeably used with anything else.
  2. print() is a function that outputs what you give it to the terminal. It will work with more than just f"" and it’s also orthogonal, so you could print out integers, and other objects, and all kinds of things (with varying levels of success).
  3. You’re accidentally thinking that these two orthogonal independent things are connected an only work together. To fix this you just have to stop doing print() always with f"". Maybe practice doing only f"" for a while like I did above.

Now the reason you get an error is print() returns nothing. This then gets set to filename, and that causes an error since the filename can’t be nothing (None).

Another thing is when you make an error like this (one that’s because of a misunderstanding) you should go back and look at every time you used print() and f"" to see if you did it anywhere else.

Update: Also, it looks like you’re typing all this code in then running it. I don’t code like that. I code tiny bits of code and run every change I make to make sure it works with the previous code. It might help to throw this away and do it again from scratch but go slow and code+run frequently so you catch more errors.

1 Like

Hi @gpkesley & @zedshaw thanks for both your replies.
As @zedshaw mentions I for some reason thought that I needed to put strings into a print() - but it makes completely sense that it does not return anything except from a terminal output.

thanks again

1 Like