PerplexingParadox
PerplexingParadox

Reputation: 1196

Python - Split function returns one value instead of expected two

I'm currently creating a database API in order to get a better grasp of how APIs work. Currently fixing the errors and whatnot, when I tried the delete function (Option 3), it gives me an error and tells me that the split function is returning one value rather than two.

My guess is that it's either reading the lines incorrectly, or through reading the text file, it doesn't register the tab ('\t') but rather as a space (' ') at times.

I'm doing this through VS Code, not sure if that's a contributing factor at all with the indents and stuff. But I've got it at 4 spaces = tab like the Python IDLE does normally.

Here's the code:

import time

def add(filename):
    print('Name?')
    key = input()
    print('Phone number?')
    value = input()
    f = open(filename, "a")
    f.write(key + "\t" + value + "\n")
    f.close()

def find(filename, key):
    f = open(filename, "r")
    for line in f:
        #first stores the current key in variable
        (currentKey, currentValue) = line.split('\t', 1)
        if currentKey == key:
            return currentValue[:-1]
    f.close()

def delete(filename, key):
    f = open(filename, "r")
    f1 = open('temporary.txt', "w")
    for (line) in f:
        #Error occurs here
        (currentKey, currentValue) = line.split('\t', 1)
        if currentKey != key:
            f1.write(line)
    f.close()
    f1.close()
    import os
    os.replace('temporary.txt', filename)
    

def update(filename, key, value):
    resultfile = "temporary.txt"
    f = open(filename, "r")
    f1 = open(resultfile, "w")
    for line in filename:
        (currentKey, currentValue) = line.split('\t', 1)
        if currentKey != key:
            f1.write(line)
        else:
            f1.write(currentKey + '\t' + value + '\n')
    f.close()
    f1.close()
    import os
    os.replace(resultfile, filename)

filename = 'telephone.txt'

#Current Menu Interface
def menu():
    print("Welcome to the telephone directory")
    print("Your options are:")
    print()
    print("1) Adding")
    print("2) Finding")
    print("3) Deleting")
    print("4) Updating")
    print("5) Quitting")
    choice = input()
    return choice

#actual decision code
def decision(choice):
    loop = 1
    while loop == 1:
        if choice == '1':
            add(filename)
            choice = menu()
        elif choice == '2':
            print("What is the name of the person you are looking for?")
            key = input()
            value = find(filename, key)
            print(key + "'s phone number is: " + value)
            choice = menu()
        elif choice == '3':
            print("What is the name of the person you are looking to delete from the directory?")
            key = input()
            delete(filename, key)
            choice = menu()
        elif choice == '4':
            print("What is the name of the person?")
            key = input()
            print("What is the telephone number you want to replace it with?")
            value = input()
            update(filename, key, value)
            choice = menu()
        elif choice == '5':
            print("Thank you for using the program! Your file contents are stored in a file called 'telephone.txt'.")
            time.sleep(1)
            loop = 0
        else:
            print("Please enter a value from 1 to 5. No spaces at all.")
            choice = menu()

choice = menu()
decision(choice)

Upvotes: 0

Views: 254

Answers (1)

C.Nivs
C.Nivs

Reputation: 13106

You're iterating over the string filename, not the file handle:

def delete(filename, key):
    f = open(filename, "r")
    f1 = open('temporary.txt', "w")
    for (line) in filename: # here
        ...

Which means that you are getting each character in filename. So if filename is 'hello.txt', you'd get:

h
e
l
l
o
.
t
x
t

You should be doing

f = open(filename)
for line in f:
    # rest of loop

Or, rather:

with open(filename) as f:
    for line in f:
        # rest of loop

Last, if your lines do not contain a tab, str.split('\t') will return a single-element list, so you could do:

try:
    a, b = line.split('\t', 1)
except ValueError:
    print('No tab in line')
    continue # skip the line

Alternatively, you could raise if you want the program to stop

try:
    a, b = line.split('\t', 1)
except ValueError:
    print('No tab in line')
    raise # stop the program

Last, the best way to handle either tabs or spaces would be the way that @RufusVS suggested:

try:
    a, b = line.split(None, 1)
except ValueError:
   # either raise or continue
   print('Line doesn't contain a whitespace separator')
   continue

Where str.split gets passed None because the function is expecting a separator argument, and omitting it will raise an error:

x = 'abc def'

x.split(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str or None, not int

x.split(None, 1)
['abc', 'def']

Upvotes: 2

Related Questions