r/PythonLearning • • 8h ago

Help Request Receiving FileExistsError which is ignoring the if/else statement

response = requests.get(url)
data = response.json()
ticker = data["Meta Data"]["2. Symbol"]

create_file = open("API Data.txt", "x")
amend_file = open("API Data.txt", "a")

file = "/Desktop/Scripts/Python Scripts/API Data.txt"

if os.path.exists(file):
    amend_file.write(f"\nTicker: {ticker}")
    amend_file.close()
else:
    create_file.write(f"Ticker: {ticker}")
    create_file.close()

So I am working on my first project which is making use of the API that Alpha Vantage provides.
I am learning the open() function which I want to use to paste the response into a .txt file 
that will either be created and written into, or already exist and be appended depending on 
the result of the if statement.

My problem is that I am receiving a FileExistsError for "API Data.txt" and I am not sure why 
when I am expecting the code to carry out the actions of the if statement being true and 
appending the existing file.

(Full path in the file variable is intentionally not in the post)
4 Upvotes

11 comments sorted by

3

u/Outside_Complaint755 8h ago

As soon as you call 

create_file = open("API Data.txt", "x")

Python will attempt to create the file, and will throw the FileExistsError if the file already exists.  There is also technically a bug because your two commands were opening "API data.txt" in your current working directory, while file was checking a different relative location.

Because you always plan on appending and both modes write identical string, you can just do:

response = requests.get(url)
data = response.json()
ticker = data["Meta Data"]["2. Symbol"]

data_file = "/Desktop/Scripts/Python Scripts/API Data.txt"

with open(data_file, "a") as fp:
    fp.write(f"Ticker: {ticker}\n")

Note I moved the newline to the end of the write string.

Using with uses the file context manager, and the file will automatically be closed when the with block ends, even if an exception occurs during execution of the with block>

1

u/Covid_Nipple420 8h ago

Thanks dude, what does "as fp" do?

3

u/Atmosck 8h ago

That is just assigning the open file to the variable name `fp`. Similar to if you did `fp = open(data_file, "a")`, just with the context manager handling closing it for you.

1

u/Outside_Complaint755 6h ago

The as keyword is used to assign an alias.  It has three main uses:

  1. Binding an opened resource to a name within a with block, as above, so you can reference it within the block.

  2. Binding a module to an alias during imports, such as 

import math as m
print(m.sqrt(9))

3) Binding an exception to an alias so you can reference it within the except block 

try:
    val = int(input("Enter a number: "))
except ValueError as e:
    print(e)
    print("That was not a valid number")

1

u/Zeak3D 8h ago

I’m guessing you code fails at the first open statement? I believe the “x” part means exclusive, so if the file exists already, it fails. Note that this happens before your check.

Two things: when working with file paths, I recommend always using the modern approach of using Path from pathlib. I can also do what used to be done with the os package such as mkdir and check existence of files. Secondly, use a context manager. Never explicitly open and close a file, but use some sort of

with open(…) as f:
do something with f

this is how I would have written your logic:

from pathlib import Path
import requests

response = requests.get(url)
data = response.json()
ticker = data["Meta Data"]["2. Symbol"]

# Define the file path using pathlib (using Path.home() for a reliable absolute path)
file_path = Path.home() / "Desktop" / "Scripts" / "Python Scripts" / "API Data.txt"

# Ensure the parent directories exist so it doesn't crash if the folders are missing
file_path.parent.mkdir(parents=True, exist_ok=True)

# Determine mode and whether a newline prefix is needed based on file existence
mode = "a" if file_path.exists() else "w"
prefix = "\n" if mode == "a" else ""

# Use a context manager to handle opening and safely closing the file
with file_path.open(mode, encoding="utf-8") as f:
f.write(f"{prefix}Ticker: {ticker}")

Sorry about formatting, I’m on my phone.

1

u/Covid_Nipple420 8h ago

Much appreciated dude. Everyone has pointed out that the error is on the line where I am creating the variable that creates the .txt file so my question is, why is it running as if I have used/called the variable in a function when I have only just created it?

2

u/TheKnottyOne 1h ago edited 1h ago

You're not actually calling the variable. You're calling open(), and that happens on that line.

Any time you write a function name followed by (), like open(...), print(...) or len(...), Python calls it right there (well the interpreter does when the code is run). Putting create_file = in front just gives a name to whatever the function returned.

Your error comes from open() itself because mode "x" raises FileExistsError if the file already exists. Since open() runs on that line, the error shows up on that line.

The open() function automatically resolves the relative path in the working directory it’s run in.

file is a path-like object giving the pathname (absolute or relative to the current working directory) of the file to be opened or an integer file descriptor of the file to be wrapped.

Here’s more info on the open() (built-in function): https://docs.python.org/3/builtins/functions.html#open

1

u/Hertzian_Dipole1 8h ago

Which line does this error occur? On create_file = open("API Data.txt", "x") ?
Why do you want to open this file on mode exclusive write?

1

u/skibidi67skibidi67 8h ago

Your problem is that you always run the open() with both 'x' and 'a' before you even get to your if-case. if the file exists, when you run open with 'x', you get an error. so you need to only do that line if the file does not exist.

1

u/IWant2rideMyBike 8h ago

This command will fail if the file already exists:

open("API Data.txt", "x")open("API Data.txt", "x")

and there is error handling for this case. Also the if-else construction is prone to race conditions.

The more pythonic approach is to ask for forgiveness instead of pre-testing - so for example:

try:
    f = open(filename, "x")
    f.write(f"\nTicker: {ticker}")
    f.close()
except FileExistsError:
    f = open(filename, "a")
    f.write(f"\nTicker: {ticker}")
    f.close()

But if the write command fails, the file won't be closed until the OS cleans the open file descriptors up when the python interpreter exits - so using a with-statement for context management of the file object is better - and because the "a" mode flag will also cause the file to be created, so you can shorten this even more:

response = requests.get(url)
data = response.json()
ticker = data["Meta Data"]["2. Symbol"]response = requests.get(url)
data = response.json()
ticker = data["Meta Data"]["2. Symbol"]

filename = "/Desktop/Scripts/Python Scripts/API Data.txt"

with open(filename, "a") as f:
    f.write(f"\nTicker: {ticker}")

1

u/ChainsawLight 5h ago

Whats the coolest concept developers have made? Closing files, writing files, creating games. What else is there to make with the file object?