ckmb
ckmb

Reputation: 75

Python - Range()

I'm new to Python, I have tried to create a simple loop in order for me to list users that has userID of value integer. However the userID on the DB seems weird (Users 1-72 are displayed properly, next to 72 is 712 already), so I need to skip those users who does not have any userID 73-711. What exception must be done or do I need to create a simple if else?

for iD in range(1, 720):
        loginID = iD
        for users in tls.getUserByID(loginID):
            fname = users.get('firstName')
            lname = users.get('lastName')
            print(loginID, fname +" "+ lname)

The error I'm getting is..

raise testlinkerrors.TLResponseError(
testlink.testlinkerrors.TLResponseError: NO_USER_BY_ID_LOGIN: (getUserByID) - Cannot Find User with DB ID (73)

Upvotes: 0

Views: 264

Answers (6)

kodemetrics
kodemetrics

Reputation: 76

You can try this @ckmb

     for iD in range(60, 720):
        if iD not in [* range(73, 712)]:
            loginID = iD
            try:
                api_getUser = tls.getUserByID(loginID)
                for user in api_getUser:
                  fname = user.get('firstName')
                  lname = user.get('lastName')
                  print(loginID, fname + " " + lname)
            except testlinkerrors.TLResponseError:
                print(loginID, "not found")
                continue
          

Upvotes: 1

Copperfield
Copperfield

Reputation: 8510

There are a number of way to get some subset of some range of number

If you know the boundaries you can use chain

>>> import itertools
>>> list(itertools.chain(range(10),range(100,110),range(210,222)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221]
>>> 

for your example is itertools.chain(range(73),range(712,720)), that way you don't waste time with something you alredy know is not going to work.

You can use filtering like in Chris answer

You can use try-except and just processing the successful ones

You can combine the two above by remembering the problematic ones, saving it somewhere, and use that to filter. For the saving part, if we want to remember after closing the program, we can use json module to save it into a file

Like for example

from testlink.testlinkerrors import TLResponseError
import json

ignore_file = "ignore_id.json" 
#to_ignore = set()

def fun(users, to_ignore=()):
    to_ignore = set(to_ignore)
    for iD in users:
        loginID = iD
        if iD in to_ignore:
            print(loginID, "ignored !")
            continue 
        try:
            users = tls.getUserByID(loginID)
        except TLResponseError:
            print(loginID, "not found !")
            to_ignore.add(iD)
            continue
        for user in users:
            fname = user.get('firstName')
            lname = user.get('lastName')
            print(loginID, fname +" "+ lname)
    return to_ignore


def load_json(file_name):
    try:
        with open(file_name) as file: 
            return json.load(file)
    except FileNotFoundError:
        return []

def save_json(file_name,data):
    with open(file_name,"w") as file:
        json.dump(data,file)




to_ignore = fun(range(1,720), load_json(ignore_file))
save_json(ignore_file,list(to_ignore))

EDIT:

You can also generalize the function to take the user and the list to ignore and whatever else it might need, and it can return the set of problematic user it found along the way and do something appropriate with that info.

Now with the function now generalize like that, you can do different types of call such as

fun(range(1,720))
fun(itertools.chain(range(73),range(712,720))
fun(range(1,113)) #for the other database
etc...

Upvotes: 1

ckmb
ckmb

Reputation: 75

I have used the answer of @Jason Yang - and it seems this is what I'm expecting to have, however I believe skipping 73-711 will increase runtime, are there any ways on how to automatically skip them? Like if these int are not present in the range, then skip

for iD in range(60, 720):
        loginID = iD
        try:
            api_getUser = tls.getUserByID(loginID)
        except testlinkerrors.TLResponseError:
            print (loginID, "not found")
            continue
        for user in api_getUser:
            fname = user.get('firstName')
            lname = user.get('lastName')
            print(loginID, fname + " " + lname)

Upvotes: 1

Jason Yang
Jason Yang

Reputation: 13061

You will get exception when call tls.getUserByID(loginID) if no user with DB ID, so you need to handle the exception testlinkerrors.TLResponseError by try/except statement.

from testlink.testlinkerrors import TLResponseError

for iD in range(1, 720):
    loginID = iD
    try:
        users = tls.getUserByID(loginID)
    except TLResponseError:
        print(loginID, "not found !")
        continue
    for user in users:
        fname = user.get('firstName')
        lname = user.get('lastName')
        print(loginID, fname +" "+ lname)

Upvotes: 2

Chris
Chris

Reputation: 36536

You could write a simple function that takes an iterable and a range of numbers to skip and returns a generator.

def skip(iter, start, end):
    return (i for i in iter if not (i <= end and i >= start))

And now:

list(skip(range(1, 720), 73, 711))

Yields:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 
 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 
 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 
 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 
 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 
 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 712, 713, 
 714, 715, 716, 717, 718, 719]
>>>

Upvotes: 1

Daniel
Daniel

Reputation: 12026

You can skip the failures with a simple try/except block.

for iD in range(1, 720):
        loginID = iD
        try:
            for users in tls.getUserByID(loginID):
                fname = users.get('firstName')
                lname = users.get('lastName')
                print(loginID, fname +" "+ lname)
        except testlinkerrors.TLResponseError:
            print("Skipping iD")
            continue

Upvotes: 1

Related Questions