Nayden Van
Nayden Van

Reputation: 1569

Python for loop iterate only once

Basic question but its confusing me a lot.

I have a csv file with roughly 4300 rows.

I need to send each row to a service which has a size limitation, so I cannot process all the rows at once.

So my idea was to have a function, that triggers in a for loop for each row in the csv file.

So here is what I have done.

with open('final_result.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        to_queue.append(row)

for msg in to_queue:
    # print(msg)
    def send_a_list_of_messages(sender):
        # print(to_queue)
        message = [ServiceBusMessage(str(msg))]
        sender.send_messages(message)
        print("msg sent: " + str(msg))

What I am expecting from this, is that the msg should get each value from the csv file in a progressive manner, pass it to the function and send it.

In a way this is what happens, but it does send only the last row of the csv file. I was wondering what am I doing wrong in this? how can I have this for loop to trigger the inner function for each row in the csv?

EDIT:

This is the whole code:

def send_a_list_of_messages(sender):
    # print(to_queue)
    message = ServiceBusMessage(str(msg))
    sender.send_messages(message)
    print("msg sent: " + str(msg))

with open('final_result.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        to_queue.append(row)

for msg in to_queue:
    send_a_list_of_messages(msg)



servicebus_client = ServiceBusClient.from_connection_string(conn_str=CONNECTION_STR, logging_enable=True)
#
with servicebus_client:
    sender = servicebus_client.get_queue_sender(queue_name=QUEUE_NAME)
    with sender:
        send_a_list_of_messages(sender)

print("Done sending messages")
print("-----------------------")

with servicebus_client:
    receiver = servicebus_client.get_queue_receiver(queue_name=QUEUE_NAME, max_wait_time=5)
    with receiver:
        for msg in receiver:
            print("Received: " + str(msg))
            receiver.complete_message(msg)

the function is called in service_client

Upvotes: 0

Views: 358

Answers (2)

Axe319
Axe319

Reputation: 4365

In it's current form it can't work for a few reasons.

When you redefine a function in a for loop it shadows (overwrites) the previous iteration of the function. So only the final definition survives.

There are a few things you can do to fix this.

  1. Directly pass the list of messages to the function:
def send_a_list_of_messages(sender, messages):
    for msg in messages:
        message = ServiceBusMessage(str(msg))
        sender.send_messages(message)
        print("msg sent: " + str(msg))

to_queue = []
with open('final_result.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        to_queue.append(row)

servicebus_client = ServiceBusClient.from_connection_string(
    conn_str=CONNECTION_STR, 
    logging_enable=True
)
with servicebus_client:
    sender = servicebus_client.get_queue_sender(queue_name=QUEUE_NAME)
    with sender:
        send_a_list_of_messages(sender, to_queue)
  1. call the function in a loop.
def send_a_single_message(sender, msg):
    message = ServiceBusMessage(str(msg))
    sender.send_messages(message)
    print("msg sent: " + str(msg))

to_queue = []
with open('final_result.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        to_queue.append(row)

servicebus_client = ServiceBusClient.from_connection_string(
    conn_str=CONNECTION_STR, 
    logging_enable=True
)
with servicebus_client:
    sender = servicebus_client.get_queue_sender(queue_name=QUEUE_NAME)
    with sender:
        for msg in to_queue:
            send_a_single_message(sender, msg)

It's good practice to include everything your function needs in the form of arguments and not rely on external variables.

For example, if you don't hand msg as an argument it will only work on the condition that msg is defined externally in the same file. This does not promote reusability.

Upvotes: 0

Phorys
Phorys

Reputation: 379

You need to define your function before calling it. In the example you posted, you are defining your function repeatedly, but not calling it. So, you need to define the function and then call it from within the loop.

EDIT: I adjusted the code after the edit and your issue appears to be that the sender was not assigned a value before you attempted to send the message.

def send_a_list_of_messages(sender, msg):
    # print(to_queue)
    message = ServiceBusMessage(str(msg))
    sender.send_messages(message)
    print("msg sent: " + str(msg))

with open('final_result.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        to_queue.append(row)

servicebus_client = ServiceBusClient.from_connection_string(conn_str=CONNECTION_STR, logging_enable=True)
sender = servicebus_client.get_queue_sender(queue_name=QUEUE_NAME)

for msg in to_queue:
    send_a_list_of_messages(sender, msg)

print("Done sending messages")
print("-----------------------")

receiver = servicebus_client.get_queue_receiver(queue_name=QUEUE_NAME, max_wait_time=5)
for msg in receiver:
    print("Received: " + str(msg))
    #I'm not certain what the receiver.complete_message does, but remember that you call this in a loop.
    receiver.complete_message(msg)

Upvotes: 1

Related Questions