-1

I'm trying to create a food storage application that tracks the items put in a food storage facility and recalls them for the user. This is a very early prototype of the program, only capable of tracking the information locally, but I ran into some problems with it. So my apologies if this code is unreadable, I just can't find a solution to my problem explained below.

print("Food Storage Application V1.0 - LOCAL ONLY")
UPC_List = []
with open('UPCList.txt', 'r') as file:
    for UPCentry in file:
        location = UPCentry[:-1]
        UPC_List.append(location)
print(UPC_List)


global i
i = 0
UPC_Input = ''
UPC_Count = 0
while True:
    UPC_Found = False
    UPC_Input = input("Enter UPC or enter 'end' to quit: ")
    if UPC_Input == "end":
        with open("UPCList.txt", "w") as file:
            for UPCsave in UPC_List:
                file.write('%s\n' % UPCsave)
        break
    try:
        UPC_Input = int(UPC_Input)
    except ValueError as v:
        print(f"Input '{UPC_Input}' is not an acceptable UPC")
        continue

    # print(UPC_List) # for debugging

    def newProduct(UPC):
        global UPC_Count
        product_name = input(f"Enter name of item {UPC}: ")
        product_quantity = input(f"Enter quantity of item {UPC}: ")
        try:
            product_quantity = int(product_quantity)
        except ValueError as v:
            print("Invalid quantity. Please enter a number.")
            newProduct(UPC_Input)
        product_unit = input(f"Enter unit type (box, bunch, can, etc...) of item {UPC}: ")
        print(f"You have added: \n {product_name} \n {UPC} \n Quantity: {product_quantity} \n Unit: {product_unit}")
        UPC_List.insert(UPC_Count, [UPC, product_name, product_quantity, product_unit])
        UPC_Count += 1
    
    def existingProduct(UPC):
        for sublist in UPC_List:
            if str(UPC) in str(sublist):
                UPC = int(UPC)
                print(f"Position: {UPC_List.index(sublist)} {sublist.index(UPC)}")
                position = UPC_List.index(sublist)
                addition = input(f"Enter the number of items to add to '{UPC_List[position][1]}' (Default entry: +1): ")
                try:
                    addition = int(addition)
                except ValueError as v:
                    addition = 0
                
                if addition == 0:
                    UPC_List[position][2] += 1
                else:
                    UPC_List[position][2] += addition
                print(f"New Quantity for item '{UPC_List[position][1]}': {UPC_List[position][2]}")

    #Find if UPC Exists
    for UPC in UPC_List:
        if UPC[0] ==  UPC_Input:
            print("UPC Found")
            existingProduct(UPC_Input)  
            UPC_Found = True
    if UPC_Found == False:
        newProduct(UPC_Input)

This is my code so far. I made a version of it without the read and writing to file lines and it worked great, but I'm stumped on getting the code to read a list from a file and use it in the code. It saves the list, but it won't retrieve it correctly. I found what I think is the problem by using that print(UPC_List) line, which prints ["[2, 'banana', 2, 'bunch']"] (that was a test entry I loaded into the file using the program). I think the problem lies in the double quotes on the outside of the list. This is a nested list, so those quotation marks lead to an index error when I try to access the list.

If this isn't enough info, I can try to provide more. I'm very new to python and coding in general so this was my best attempt at the script.

  • Include a small example of the contents of the input file. – jarmod Feb 09 '22 at 17:03
  • Don't post your full code here, there's a lot of unnecessary stuff. And we don't know what the contents of `UPCList.txt` even are, so this post doesn't even have all the *necessary* info. Please read the [mre] page. – Random Davis Feb 09 '22 at 17:04

2 Answers2

0

You are reading each list in as a string.

You can use the python eval function to convert a string into its evaluated form:

my_list_string = "['item1', 'item2']"
my_list = eval(my_list_string)
  • That repaired it. Thanks! – steelscape02 Feb 09 '22 at 17:15
  • 1
    Please remember the [__security issues when using `eval()`__](https://realpython.com/python-eval-function/#minimizing-the-security-issues-of-eval). For example writing `quit()` to the file would result in terminating your program (unexpectedly) when reading the file - try ` str = 'quit()'; eval(str)` – hc_dev Feb 09 '22 at 18:15
0

To reproduce and solve, we need a minimal reproducible example including

  • the input (file contents posted as plain-text in code-block formatting)
  • the minimal code to reproduce

Input file

Contents of UPCList.txt:

[2, 'banana', 2, 'bunch']

This is the string-representation of a list in Python (like str(list)). Probably it was written by your program.

Code

a minimal reproducible example (only first few lines to print the read list):

upc_locations = []
with open('UPCList.txt', 'r') as file:
    for upc in file:
        location = upc[:-1]
        upc_locations.append(location)
print(upc_locations)

Prints:

["[2, 'banana', 2, 'bunch']"]

Debug

add some debug print for each line read

upc_locations = []
with open('UPCList.txt', 'r') as file:
    for line in file:
        print(line)
        location = line[:-1]  # read all chars from line until last (excluding)
        print(location)
        upc_locations.append(location)
print(upc_locations)

Prints:

[2, 'banana', 2, 'bunch']

[2, 'banana', 2, 'bunch']
["[2, 'banana', 2, 'bunch']"]

Note:

  1. the second empty-line is the line-break \n at the end of the file's line.
  2. the first line contains something like a Python list with strings and numbers
  3. the third line has removed the line-break.

Fix

The line can be parsed as JSON array. Therefore we need to replace the single-quotes by double-quotes first.

import json

upc_locations = []
with open('UPCList.txt', 'r') as file:
    for line in file:
        cleaned = line.strip()  # remove the line-break and any surrounding whitespace
        print(cleaned)
        valid_json = cleaned.replace("'", '"')  # replace single quotes by double quotes to have valid JSON strings
        array = json.loads(valid_json)
        print(array)
        for element in array:
            upc_locations.append(element)
print(upc_locations)

Prints:

[2, 'banana', 2, 'bunch']
[2, u'banana', 2, u'bunch']
[2, u'banana', 2, u'bunch']

Tip: save your objects as JSON to a file

When saving objects from your programs to a plain text-file it is recommended to use a standard format like CSV, XML or JSON. So you can use standard-parsers to read it (back).

For example:

import json

def save(list):
    with open("UPCList.txt", "w") as file:
    json.dump(list, file)
    # file.write('%s\n' % UPCsave)


def load():
    with open("UPCList.txt", "r") as file:
    return json.load(file)

Note:

  • The out-commented line wrote the list in Python's string-representation (see precent-formatting %s). Thus we had to replace the double-quotes when reading.
  • The json-dump writes a list as JSON-array. This format is readable by many programs and tools and the defacto web-standard.

See also:

hc_dev
  • 8,389
  • 1
  • 26
  • 38