Short anser is yes, and how the output will look depends on which method you use.
For example if you want to use concurrent.futures, you can print the output as it is performed inside the function, and order will be scrambled.
If you instead want to access return values, you can chose if you want to access them as they are completed, in whichever order they happen to finish, or you can use the "map" function to retrieve them in the expected order.
import concurrent.futures
def test_function(arguments: tuple):
test_value, function = arguments
"""Print the test value 1000 times"""
for i in range(0, 1000):
print(f"Function {function}, {test_value}, iteration {i}")
return test_value
def main():
"""Main function"""
# Context manager for parallel tasks
with concurrent.futures.ThreadPoolExecutor() as executor:
# Submit example. Executes the function calls asynchronously
result = [executor.submit(test_function, (i, "submit")) for i in range(1, 21)]
# Map example.
# Takes an iterable as argument that will execute the function once for each item
result_2 = executor.map(test_function, [(i, "map") for i in range(1, 21)])
for future in concurrent.futures.as_completed(result):
print(f"Submit: Process {future.result()} completed")
for future in result_2:
print(f"Map: Process {future} completed")
if __name__ == '__main__':
main()