0

I have the following function logic.

def funct(arg):
    ...
    return result_list

param_list = ['param1','param2']
for my_arg in param_list
    my_results = funct(my_arg)

How do I get the full list of results for running the function on both parameters? Is there a better way to organize this?

Following one of the answers I tried to apply that logic buy I'm not getting the desired results:

from pythonping import ping
from log_class import NetddLog

def ip_probe(ip, ip_probe_logger, ipsl):

    def ping_ip():
        try: 
            ip_probe_logger.info(f"Pinging {ip} started")
            result = ping(ip, count=5, df=True, payload='64')
            ip_probe_logger.info(f"Pinging {ip} succeded")
        except Exception as err:
            ip_probe_logger.error(f"Pinging {ip} failed {err}")

    def trace_ip():
        #function for traceroute
        pass

    ping_ip()
    #trace_ip()
    
    log_contents = ip_probe_logger.log_capture_string.getvalue()
    ipsl.append(log_contents)

    return ipsl

if __name__ == "__main__":
    ipsl = ['Start']
    ip_probe_logger = NetddLog("IP_PROBE", level="INFO") 
    ip_list = ["192.168.255.68", "192.168.254.108"]
    for ip in ip_list:
        ipsl.extend(ip_probe(ip, ip_probe_logger, ipsl))
    print('')
    for log_item in ipsl:
        print(log_item.rstrip())

I get a result with lots of repetition, but what I am trying to achieve is adding each individual ping result to IPSL list after the first 'Start' item.

Start
2022-03-24 01:12:48,444|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:12:48,770|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
Start
2022-03-24 01:12:48,444|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:12:48,770|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
2022-03-24 01:12:48,444|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:12:48,770|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
2022-03-24 01:12:48,772|IP_PROBE|INFO: Pinging 192.168.254.108 started
2022-03-24 01:12:49,078|IP_PROBE|INFO: Pinging 192.168.254.108 succeded
Start
2022-03-24 01:12:48,444|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:12:48,770|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
Start
2022-03-24 01:12:48,444|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:12:48,770|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
2022-03-24 01:12:48,444|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:12:48,770|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
2022-03-24 01:12:48,772|IP_PROBE|INFO: Pinging 192.168.254.108 started
2022-03-24 01:12:49,078|IP_PROBE|INFO: Pinging 192.168.254.108 succeded

By changing the body of for loop to: ip_probe(ip, ip_probe_logger, ipsl) I still get a repetition probably because of the second function return.

Start
2022-03-24 01:22:32,829|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:22:33,235|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
2022-03-24 01:22:32,829|IP_PROBE|INFO: Pinging 192.168.255.68 started
2022-03-24 01:22:33,235|IP_PROBE|INFO: Pinging 192.168.255.68 succeded
2022-03-24 01:22:33,236|IP_PROBE|INFO: Pinging 192.168.254.108 started
2022-03-24 01:22:33,504|IP_PROBE|INFO: Pinging 192.168.254.108 succeded
JON
  • 127
  • 1
  • 10

4 Answers4

2

Make my_results a list, and extend it on each call.

my_results = []
for my_arg in param_list
    my_results.extend(funct(my_arg))
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • oh, I hadn't appreciated that the return of `funct` is a _list_; they may really benefit from a generator in such a case outside of the Question – ti7 Mar 23 '22 at 16:30
  • I assumed so from the line `return result_list` – Barmar Mar 23 '22 at 16:31
  • @Barmar Hello again. I implemented your answer on clean code and it worked, but when trying to implement on my function I get strange results. Can you review the code I just posted and give me an idea how to improve it? – JON Mar 24 '22 at 05:21
  • `ip_probe` appends to the `ipsl` list itself, there's no need to do it again in the `for` loop in main. – Barmar Mar 24 '22 at 16:03
1

If you want a single message, create a dictionary mapping the inputs to the outputs and pack it all at once

Beware very large dicts can be troublesome and you may want to truncate it, base64-encode it, or do other work to reduce the result size

results = {}
for my_arg in param_list
    results[my_arg] = funct(my_arg)

logger.info(f"results mapping: {results}")
ti7
  • 16,375
  • 6
  • 40
  • 68
  • This looks good, its just that I need to work with lists. Can you review my updated code following one of the previous answers? @ti7 – JON Mar 24 '22 at 05:28
0

This is a rare case where you may actually want generator delegation, which could make your functions much more efficient (as they can avoid creating intermediate lists, which are only discarded)

def funct(input_value):
    for result in some_source(input_value):
        yield result

def funct_wrapper(input_values):
    for input_value in input_values:
        yield from funct(input_value)

Collect and use the results, adding them to some collection to display later

ti7
  • 16,375
  • 6
  • 40
  • 68
  • Unfortunately, as a beginner implementing generator delegation is a bit to much for me, so I'm not sure how that would work in practice – JON Mar 24 '22 at 05:26
0

Make my_results as list and append or extend it for each iterations. Here is an example:

def funct(arg):
    ....
    return result_list
my_results=[]
param_list = ['param1','param2']
for my_arg in param_list:
    my_results.append(funct(my_arg))
# print(my_results)
Esraa Abdelmaksoud
  • 1,307
  • 12
  • 25
Peter
  • 51
  • 3