Python Forum
Loop with choose - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Loop with choose (/thread-34599.html)



Loop with choose - Irv1n - Aug-12-2021

Hello,
I have this script:
acw = [0.500, 0.750, 1.000, 1.500, 2.000, 3.000, 3.500, 4.000, 4.500, 5.000]
for rang in acw:
    dmm.set_mode_acw(rang)
    dmm.switch_output(1)
    time.sleep(10)
    val_list_dmm = []
    val_list_nom =[]
    for num_read in range(5): # cycle 1
        val_cal = fl.read_volt_result()
        time.sleep(2)
        val_src = dmm.read_data_volt()
        val_list_nom.append(val_src*1000)
        val_list_dmm.append(val_cal)
    dmm.switch_output(0)
    mean_meas = unc_gpi.mean_calc(val_list_dmm)
    mean_source = unc_gpi.mean_calc(val_list_nom)
    error = unc_gpi.acw_uncert(rang*1000)
    abs_error = unc_gpi.abs_error(mean_source, mean_meas)
    min_error = unc_gpi.min_error(mean_source, error)
    max_error = unc_gpi.max_error(mean_source, error)
    check_status = unc_gpi.check_error(error, mean_source, mean_meas)
I need add the following to it:

if check_status == "Fail",
need to prompt the user to enter three options:
1 Re-Measure
2 Continue
3 interrupt
If you select 1, this cycle will start: from # cycle 1, from the element of the list on which the "Fail", until it "Fail" or the user chooses 2 or 3
if select 2: continue code execution
if select 3: abort and complete the code


RE: Loop with choose - deanhystad - Aug-12-2021

I think you should break out the body of the loop into a function. If check_status is fail, then you can ask for user input (which I would also write as a separate function) and take the appropriate action based on the user response.
acw = [0.500, 0.750, 1.000, 1.500, 2.000, 3.000, 3.500, 4.000, 4.500, 5.000]

def process_rang(rang):
    dmm.set_mode_acw(rang)
    dmm.switch_output(1)
    time.sleep(10)
    val_list_dmm = []
    val_list_nom =[]
    for num_read in range(5): # cycle 1
        val_cal = fl.read_volt_result()
        time.sleep(2)
        val_src = dmm.read_data_volt()
        val_list_nom.append(val_src*1000)
        val_list_dmm.append(val_cal)
    dmm.switch_output(0)
    mean_meas = unc_gpi.mean_calc(val_list_dmm)
    mean_source = unc_gpi.mean_calc(val_list_nom)
    error = unc_gpi.acw_uncert(rang*1000)
    abs_error = unc_gpi.abs_error(mean_source, mean_meas)
    min_error = unc_gpi.min_error(mean_source, error)
    max_error = unc_gpi.max_error(mean_source, error)
    return unc_gpi.check_error(error, mean_source, mean_meas)

index = 0
while index < len(acw):
    if process_rang(acw[index]) == 'Fail':
        action = get_user_action(acw[index]):  # Exercise left to the reader
        if action == 'Interrupt':
            break
        elif action == 'Continue':
            index += 1
    else:
        index += 1
Why write a function that is only called from one place? To make the code easier to understand and maintain. With slight modification you could do everything without functions.
acw = [0.500, 0.750, 1.000, 1.500, 2.000, 3.000, 3.500, 4.000, 4.500, 5.000]

index = 0
while index < len(acw):
    rang = acw.get[index]
    dmm.set_mode_acw(rang)
    dmm.switch_output(1)
    time.sleep(10)
    val_list_dmm = []
    val_list_nom =[]
    for num_read in range(5): # cycle 1
        val_cal = fl.read_volt_result()
        time.sleep(2)
        val_src = dmm.read_data_volt()
        val_list_nom.append(val_src*1000)
        val_list_dmm.append(val_cal)
    dmm.switch_output(0)
    mean_meas = unc_gpi.mean_calc(val_list_dmm)
    mean_source = unc_gpi.mean_calc(val_list_nom)
    error = unc_gpi.acw_uncert(rang*1000)
    abs_error = unc_gpi.abs_error(mean_source, mean_meas)
    min_error = unc_gpi.min_error(mean_source, error)
    max_error = unc_gpi.max_error(mean_source, error)

    if unc_gpi.check_error(error, mean_source, mean_meas) == 'Fail':
        print(f'There was an error processing {rang}.  What do you want to do')
        action = input('(C)ontinue, (E)xit, (R)etry?').upper()
        if action == 'E':
            break
        elif action == 'R':
            continue
    index += 1
This could be made to work, but it would be difficult to extend beyond this one possible failure point. And it is ugly, ugly, ugly. I feel unclean providing it as an example.


RE: Loop with choose - Irv1n - Aug-20-2021

I have error:
rang = acw.get[index]
"List[float]" has no attribute "get"

okey this may work:
rang = acw[index]



RE: Loop with choose - deanhystad - Aug-20-2021

So your takeaway is to use the ugly version that doesn't use a function.


RE: Loop with choose - Irv1n - Sep-16-2021

if I change my acw list to dcv dictionary, how now I can use this loop?
val_list_err_dcv = []
for rang in dcv:
    dmm.set_range(rng=str(rang))
    fluke.set_output_volt("0")
    fluke.switch_output(1)
    time.sleep(10)
    dmm.set_null()
    time.sleep(20)
    fluke.switch_output(0)

    for volt in dcv[rang]:
        fluke.set_output_volt(volt)
        print(f'F5720 Output{volt}')
        fluke.switch_output(1)
        time.sleep(3)
        val_list_dmm_dcv = []
        for num_read in range(5):
            val_meas_dcv = dmm.read_data()
            print(f'DMM MEAS:{val_meas_dcv}')
            val_list_dmm_dcv.append(val_meas_dcv)
        fluke.switch_output(0)
        mean_dmm = unc_f8508.mean_calc(val_list_dmm_dcv)
        error = unc_f8508.dcv_uncert_1y(volt)
        abs_error = unc_f8508.abs_error(mean_dmm, volt)
        min_error = unc_f8508.min_error(volt, error)
        max_error = unc_f8508.max_error(volt, error)
        check_status = unc_f8508.check_error(error,mean_dmm,volt)
fluke.switch_output(0)



RE: Loop with choose - deanhystad - Sep-16-2021

To use "while" to loop through a dictionary you need to extract the dictionary keys or items to a list, and use the list.