简体   繁体   中英

What am I missing here? Simple for loop in python

I'm quite new with python and I'm trying something very basic but I don't seem to get the desired result. The final goal is to send a few API calls to an endpoint by populating different details. I have a list of items I need to do something with them, the actions that need to be applied to them are different values contained in a CSV, I've figured out how to handle the different parameters and fill in in the API call properly, now I need to iterate all rows on the CSV, with their relevant parameters, over a list of items.

So I have a text file with items that looks like this:

1234 5678 3333 5555 etc...

And a CSV file with different columns that represent different parameters

Here's the code I wrote:

items_file = 'itemlist.txt'
action_file = 'actions.csv'

file_handle = open(action_file, "r", encoding="utf8")
csv_reader = DictReader(file_handle)

with open(items_file, "r") as myfile:
    item_list = myfile.read().splitlines()


def actions(arg_item_list):
    for item in range(len(arg_item_list)):
        for row in csv_reader:
            print('do something with ' arg_item_list[item]) 
            blah 
            blah...
            

actions(item_list)

file_handle.close()

The problem I'm facing is that it seems to run fine on the first item, and if I ask to print the list of items and actions it will print them fine, but when running the actual actions of sending each row params on a call for each item, it only runs on the first one and exits.

So it does what I want but only on "1234" which is the first line of the text file, all the others are not getting into the nested loop.

I know I'm missing something very basic, and I'll appreciate your kind help.

Thanks!

The csv.DictReader object is an iterator, and iterators can only be iterated over once, then they're "spent".

(And by the way, your outer loop can probably be simplified to

for item in arg_item_list:
    do_stuff_with(item)

if you need the index too, you can do

for index, item in enumerate(item_list):
    print("item number", index, "is", item)

This saves you some range(len()) and [] drill.)

Thanks Ture Pålsson for the hints, I understood the "disposable" character of the DictReader object, so I've researched this further to find a viable way to be able to reuse it as much as I can. I've found that if I convert this to a table and populate all rows with columns names and values I'm able to iterate over it similarly to what I did just as many times as I want. Here's the final code:

import csv
from csv import DictReader
from typing import List, Dict


items_file = 'itemlist.txt'
action_file = 'actions.csv'

file_handle = open(action_file, "r", encoding="utf8")
csv_reader = list(DictReader(file_handle))
table: List[Dict[str, str]] = [] #in my case, all values were strings, but you could use this also to convert it to other types, e.g. List[Dict[str, float] = [].

with open(items_file, "r") as myfile:
    item_list = myfile.read().splitlines()


for row in csv_reader:
    str_row: Dict[str, str] = {} 
    for column in row:
        str_row[column] = str(row[column])
    table.append(str_row)


def actions(arg_item_list):
    for item in arg_item_list:
        for row in table:
            print('apply actions from columns data on rows by their name e.g. ', row['action_column_1'], row['any_other_column_name']
            print('and apply them on ' arg_item_list[item]) 
            

actions(item_list)

file_handle.close()

I hope someone finds this useful!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM