In Python, all statements are executed sequentially. The first statement is executed first, followed by the second, and so on. At the same time, there are many situations when you need to execute a block of code several times. To solve this problem, the Python programming language provides us with two constructs: the for loop and the while loop. Both looping constructs provide similar functionality, but they differ in syntax and condition checking. This Python loops tutorial will cover the loop, the while loop, and the flow control statements like break and continue.
Table of contents
Python loops – “for”
You have to use for loops when you have a block of code that you want to repeat a fixed number of times.
The for loop statement iterates over the members of a sequence (list, tuple, or strings) in order and executes your code block each time. As a Cloud Automation Engineer, you’ll be using for loops a lot while working with files in Python or processing output of cloud services APIs.
Here’s the syntax of the for loop:
for VARIABLE in SEQUENCE:
statements
The following flow diagram visualizes the program execution process:

As an example, let’s print all EC2 instance IDs from the list:
#!/usr/bin/env python3
ec2_instance_ids = [
'i-0e9a442e6332682dc',
'i-0c0ce77e0b27ed800'
]
for ec2_instance_id in ec2_instance_ids:
print(f'EC2 instance ID: {ec2_instance_id}')
Here’s an output in Cloud9 IDE:

In the example above, the for loop walks through every element of ec2_instance_ids
list and assigns its value to ec2_instance_id
variable so that we can use it in the print()
statement.
range() class in Python
Sometimes, when we’re looping through a sequence, it is required to get any information about the element index.
In this case, you can use the range() class, which generates an immutable sequence of numbers.
Usually, we’re using range() in two ways:
range(stop)
– wherestop
is the last number of the sequencerange(start, stop[, step])
– wherestart
is the first value,stop
is the last number in the sequence and optionalstep
is a positive or negative number used to generate sequence numbers.
A couple of examples:
>> print(list(range(5)))
[0, 1, 2, 3, 4]
>> print(list(range(1, 3)))
[1, 2]
>> print(list(range(0, 5, 2)))
[0, 2, 4]
>> print(list(range(3, 0, -1)))
[3, 2, 1]
Iterating by index in Python
Now, as soon as we introduced a range() class, we can use this knowledge to iterate through a sequence by index.
Let’s modify our previous example to iterate ec2_instance_ids
list by the list element index:
#!/usr/bin/env python3
ec2_instance_ids = [
'i-0e9a442e6332682dc',
'i-0c0ce77e0b27ed800'
]
for i in range(len(ec2_instance_ids)):
print(f'Instance {i}: {ec2_instance_ids[i]}')
Here’s an output in Cloud9 IDE:

In the example above, the range() class will generate a sequence [0, 1]
based on ec2_instance_ids
array size, which is calculated by the len()
function.
Else statement in Python
Like in if statement for loop can have an else statement.
Python executes else statement block after a for loop has been completely executed.
If the for loop has been interrupted by the break statement, the interpreter skips else statement block.
Here’s a statement syntax:
for VARIABLE in SEQUENCE:
statements block 1
else:
statements block 2
Let’s illustrate this behavior with an example:
#!/usr/bin/env python3
print(' For loop has not been interrupted '.center(50, '='))
for i in range(0, 3):
print(i)
else:
print('Range has been processed')
print('')
print(' For loop has been interrupted '.center(50, '='))
for i in range(0, 3):
if i == 1:
break
print(i)
else:
print('Range has been processed')
Here’s an output in Cloud9 IDE:

This syntax is not widely used because it is not very intuitive, even for mature Python developers.
Nested for loops in Python
Nested for loops are commonly used when we need to process nested data structures.
While automating cloud infrastructure, you may face nested loops in the code working with EC2 instances, processing SQS messages, Kinesis streams, etc.
For example, here’s an event structure of S3->SQS->Lambda integration:
{
"Records":[
{
"messageId":"581db230-9853-4be3-a1fe-72c9a5b3e4d4",
"receiptHandle":"AQEBAwV4m8sSkn5jDd1k/GBLco1znfiv+xT0KTRZdEhQE7clWhAcFlVusMR07RQsBo5ImrlIDafWwdzfX+ZqsuRQPGWE0CcsR6ga8yQTTtG6N1CpWuotJ69Ef55XILtkOMKS+7HR3Ek1oigests3bmx5eCj0QlsRR56qSpj0o1yOOLktLsUehPPTEmWmWXGGPoTc2GayxbnL6lCheolswgiMdE2u0qmbaKV6Ek3E4PyvPfzkOx8XGXIurYJCkFMGcpi0sWrus1WO+dzbm5NtOL9n8qAzjxaMyMyV+nXvy+EO1QCLu2CuX0/rhKfjoq0+txWm8tNVb27VKbwsRKrU12odmV9mbULuvKDU55CqNOMF+LZl8zdZzceegvK2wgfA8KjMmpJ5wQVWo0S8WqVpcJCKSJYhoh/XzqGde+1gQ957YR8=",
"body":"{\"Records\":[{\"eventVersion\":\"2.1\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-east-1\",\"eventTime\":\"2021-04-26T23:25:17.884Z\",\"eventName\":\"ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"AWS:012850762433:admin\"},\"requestParameters\":{\"sourceIPAddress\":\"108.41.58.86\"},\"responseElements\":{\"x-amz-request-id\":\"74CMGJPKH3HA1G87\",\"x-amz-id-2\":\"c52dEWNgb6rNUs7MNY20ArZHLgtNFiRJIhREfnNAnlLsXHotTUvLS7InfWnkniuawxPgTlkOkTKZICwIgsbfdHDZKQvL0LcV\"},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"tf-s3-queue-20210426224851886600000002\",\"bucket\":{\"name\":\"amaksimov-s3-sqs-demo-bucket\",\"ownerIdentity\":{\"principalId\":\"A1W385KKD8Q319\"},\"arn\":\"arn:aws:s3:::amaksimov-s3-sqs-demo-bucket\"},\"object\":{\"key\":\"6.+Beginner%27s+Guide+to+AWS+Step+functions+-+AWS+HelloWorld+example.png\",\"size\":458757,\"eTag\":\"e1148e80d0798b0e23502cbdae1fef58\",\"sequencer\":\"0060874BE06812C89A\"}}}]}",
"attributes":{
"ApproximateReceiveCount":"1",
"SentTimestamp":"1619479521272",
"SenderId":"AIDAJHIPRHEMV73VRJEBU",
"ApproximateFirstReceiveTimestamp":"1619479521279"
},
"messageAttributes":{},
"md5OfBody":"7195d8d0f011fac4dc115b59d3e86797",
"eventSource":"aws:sqs",
"eventSourceARN":"arn:aws:sqs:us-east-1:012850762433:amaksimov-s3-event-notification-queue",
"awsRegion":"us-east-1"
}
]
}
This message consists of a list of Records
from SQS service.
Every record has a body
key with another nested event from the S3 bucket represented as a string:
{
"Records":[
{
"eventVersion":"2.1",
"eventSource":"aws:s3",
"awsRegion":"us-east-1",
"eventTime":"2021-04-26T23:31:08.107Z",
"eventName":"ObjectCreated:Put",
"userIdentity":{
"principalId":"AWS:012850762433:admin"
},
"requestParameters":{
"sourceIPAddress":"108.41.58.86"
},
"responseElements":{
"x-amz-request-id":"YP7DR0F7H7R1GN1S",
"x-amz-id-2":"WYvnoGQrVxe2LfV6yr/sDsZXj/QDL0vD02WQYn9zXg3jX2iKfq83omTmcOcIiuSUk4dTmRRDrhdNNzffoi8AeSBN7RHs2ab0"
},
"s3":{
"s3SchemaVersion":"1.0",
"configurationId":"tf-s3-queue-20210426224851886600000002",
"bucket":{
"name":"amaksimov-s3-sqs-demo-bucket",
"ownerIdentity":{
"principalId":"A1W385KKD8Q319"
},
"arn":"arn:aws:s3:::amaksimov-s3-sqs-demo-bucket"
},
"object":{
"key":"4.+Beginner%27s+Guide+to+AWS+Step+functions+-+HelloWorld+Example.png",
"size":9714,
"eTag":"b21c122beffd36c0f0caabc4dbd8b16d",
"sequencer":"0060874D3FC2FA681D"
}
}
}
]
}
Here’s a small Python program, which processes S3 events coming from SQS queue using nested for loop:
#!/usr/bin/env python3
import json
def handler(event, context):
for sqs_rec in event['Records']:
s3_event = json.loads(sqs_rec['body'])
for s3_rec in s3_event['Records']:
s3_bucket_name = s3_rec['s3']['bucket']['name']
s3_object_name = s3_rec['s3']['object']['key']
print(f'Bucket name: {s3_bucket_name}', s3_bucket_name)
print(f'Object key: {s3_object_name}')
if __name__ == '__main__':
sqs_event = {
"Records":[
{
"messageId":"581db230-9853-4be3-a1fe-72c9a5b3e4d4",
"receiptHandle":"AQEBAwV4m8sSkn5jDd1k/GBLco1znfiv+xT0KTRZdEhQE7clWhAcFlVusMR07RQsBo5ImrlIDafWwdzfX+ZqsuRQPGWE0CcsR6ga8yQTTtG6N1CpWuotJ69Ef55XILtkOMKS+7HR3Ek1oigests3bmx5eCj0QlsRR56qSpj0o1yOOLktLsUehPPTEmWmWXGGPoTc2GayxbnL6lCheolswgiMdE2u0qmbaKV6Ek3E4PyvPfzkOx8XGXIurYJCkFMGcpi0sWrus1WO+dzbm5NtOL9n8qAzjxaMyMyV+nXvy+EO1QCLu2CuX0/rhKfjoq0+txWm8tNVb27VKbwsRKrU12odmV9mbULuvKDU55CqNOMF+LZl8zdZzceegvK2wgfA8KjMmpJ5wQVWo0S8WqVpcJCKSJYhoh/XzqGde+1gQ957YR8=",
"body":"{\"Records\":[{\"eventVersion\":\"2.1\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-east-1\",\"eventTime\":\"2021-04-26T23:25:17.884Z\",\"eventName\":\"ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"AWS:012850762433:admin\"},\"requestParameters\":{\"sourceIPAddress\":\"108.41.58.86\"},\"responseElements\":{\"x-amz-request-id\":\"74CMGJPKH3HA1G87\",\"x-amz-id-2\":\"c52dEWNgb6rNUs7MNY20ArZHLgtNFiRJIhREfnNAnlLsXHotTUvLS7InfWnkniuawxPgTlkOkTKZICwIgsbfdHDZKQvL0LcV\"},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"tf-s3-queue-20210426224851886600000002\",\"bucket\":{\"name\":\"amaksimov-s3-sqs-demo-bucket\",\"ownerIdentity\":{\"principalId\":\"A1W385KKD8Q319\"},\"arn\":\"arn:aws:s3:::amaksimov-s3-sqs-demo-bucket\"},\"object\":{\"key\":\"6.+Beginner%27s+Guide+to+AWS+Step+functions+-+AWS+HelloWorld+example.png\",\"size\":458757,\"eTag\":\"e1148e80d0798b0e23502cbdae1fef58\",\"sequencer\":\"0060874BE06812C89A\"}}}]}",
"attributes":{
"ApproximateReceiveCount":"1",
"SentTimestamp":"1619479521272",
"SenderId":"AIDAJHIPRHEMV73VRJEBU",
"ApproximateFirstReceiveTimestamp":"1619479521279"
},
"messageAttributes":{
},
"md5OfBody":"7195d8d0f011fac4dc115b59d3e86797",
"eventSource":"aws:sqs",
"eventSourceARN":"arn:aws:sqs:us-east-1:012850762433:amaksimov-s3-event-notification-queue",
"awsRegion":"us-east-1"
}
]
}
handler(sqs_event, {})
Here’s an output in Cloud9 IDE:

In the example above, we’re using:
- For loop to walk through a list of Records of SQS event (line 6)
- Python JSON module to convert S3 event from string to a dictionary (line 7)
- Nested for loop to process list of Records of S3 event (line 9) and get information about S3 bucket and object key which generated the event (lines 10-11)
Python loops – “while”
In python, we’re using a while loop to execute a code block untill the test expression returns True.
Generally, we need to use a while loop when we don’t know the exact number of iterations beforehand.
Here’s the syntax of the while loop:
while TEST_EXPRESSION:
statements
The following flow diagram visualizes the program execution process:

Here’s a list of important notes about the while loop:
- In the while loop, the test expression is checked first, and the body of the loop is entered only if
TEST_EXPRESSION
equalsTrue
. - After every iteration, the test expression is checked again, and this process continues until the
TEST_EXPRESSION
returnsFalse
. - Python interprets any non-zero value returned in
TEST_EXPRESSION
asTrue
. None
and0
are interpreted asFalse
.
Iterating by list index in Python
Let’s implement iteration over EC2 instances list using while loop:
#!/usr/bin/env python3
ec2_instance_ids = [
'i-0e9a442e6332682dc',
'i-0c0ce77e0b27ed800'
]
instance_number = 0
while instance_number < len(ec2_instance_ids):
print(f'EC2 instance ID: {ec2_instance_ids[instance_number]}')
instance_number += 1
Here’s an output in Cloud9 IDE:

Processing lists using iterator in Python
In addition to indexes, you can use iterators for processing while loop in Python.
There’s no difference between iterators and indexes for small data sets, but for a large data sets, usage of iterators saves you memory and execution time (StackOverflow).
Here’s an example of using iterator for processing the same list of EC2 instances:
#!/usr/bin/env python3
ec2_instance_ids = [
'i-0e9a442e6332682dc',
'i-0c0ce77e0b27ed800'
]
iterator = iter(ec2_instance_ids)
while True:
try:
ec2_instance_id = next(iterator)
print(f'EC2 instance ID: {ec2_instance_id}')
except StopIteration:
break
Here’s an output in Cloud9 IDE:

A couple of comments about the example above:
- We’re making the list of EC2 instances iterable by using
iter()
function (line 8). - An infinite while loop (line 10) is walking through the list of EC2 instance IDs.
- In the
try block
(line 11), we fetch the next element ofec2_instance_ids
list withnext()
function (line 12). - When the
next()
function raises theStopIteration
exception (line 12), we’re breaking the loop execution (lines 14-15)
Nested while loops in Python
In the same way, as nested for loop, you can use nested while loops.
while TEST_EXPRESSION_1:
statements_block_1
while TEST_EXPRESSION_2:
statements_block_2
statements_block_3
In the syntax example above, while loop on line 1 executes:
statements_block_1
(line 2)- Nested while loop with its own
TEST_EXPRESSION_2
(line 4) andstatements_block_2
(line 5) statements_block_3
(line 7)
Else statement in forl loop in Python
Similar to the else statement in the for loop, you can use the else statement with the while loop in the same way.
The same rules will apply:
#!/usr/bin/env python3
ec2_instance_ids = [
'i-0e9a442e6332682dc',
'i-0c0ce77e0b27ed800'
]
print(' While loop has not been interrupted '.center(50, '='))
instance_number = 0
while instance_number < len(ec2_instance_ids):
print(f'EC2 instance ID: {ec2_instance_ids[instance_number]}')
instance_number += 1
else:
print('Done!')
print(' While loop has been interrupted '.center(50, '='))
iterator = iter(ec2_instance_ids)
while True:
try:
ec2_instance_id = next(iterator)
print(f'EC2 instance ID: {ec2_instance_id}')
except StopIteration:
break
else:
print('Done!')
Here’s an output in Cloud9 IDE:

Flow control in Python
Flow control statements change the flow execution normal behavior.
Three statements allow us to control the loop execution process:
continue
break
- pass
Let’s introduce them one by one.
Continue in Python
The continue statement returns the control to the beginning of the loop.
In most Python programs, we use continue statement to skip processing of a sequence element, for example:
#!/usr/bin/env python3
for i in range(4):
if i == 2:
continue
print(i)
print('End of the program')
Here’s an output in Cloud9 IDE:

Break in Python
The break statement immediately exits the loop.
This statement is commonly used in complex search operations to break the search process if the result has been found:
#!/usr/bin/env python3
for i in range(4):
if i == 2:
break
print(i)
print('End of the program')
Here’s an output in Cloud9 IDE:

Pass in Python
The pass statement allows us to declare empty loops, functions, classes, and if statements.
In real life, we use this statement when we know that we need a loop, function, or class but do not want to implement it yet.
For example, this is a valid Python program:
#!/usr/bin/env python3
ec2_instance_ids = [
'i-0e9a442e6332682dc',
'i-0c0ce77e0b27ed800'
]
for i in range(len(ec2_instance_ids)):
# Implement code to process instances
pass
print('End of the program')
Here’s an output in Cloud9 IDE:
