python NoneType object is not iterable

17,233

Solution 1

I would guess that the problem is on the last line, is should be dedented (reduce the indentation by one level). In your current code, when the file is not found, the function will return None. And your NoneType error might occur on the code using the output of this function.

Try reduce the indentation of your return statement.

EDIT:

Seeing your traceback, this issue is confirmed to be the error, as it can't unpack None into game1 and board1

Solution 2

The indentation of the return statement

return g,b

makes it a part of the else in you function. If the file cannot be opened, you create a new game

g,b = creategame()

but never return it. So maybe the code that consumes the values returned by this function raises the error. You should de-indent (if there's such a word) the return statement to make it a part of the function code and not the else branch

Or maybe the creategame() returns None and your line g,b = creategame() raises the error.

For such questions posting (and analyzing) the traceback will help you debug the code faster.

Share:
17,233
Saume
Author by

Saume

Updated on June 04, 2022

Comments

  • Saume
    Saume almost 2 years

    This code runs fine when "filename" is a file that exists... when it doesn't, however... I keep getting the same error: TypeError: 'NoneType' object is not iterable (Errno 2)

    Even though i never iterate on anything unless a file is opened at the very start of the function. I've looked over my code many times over and can not find where i would iterate on an object that is not iterable.

    NB. I've also tried with "except IOError" and I get the same result.

    The function takes only one argument, its the variable "filename"

    Taceback:

    Traceback (most recent call last):
      File "C:\Users\Saume\Workspace\Chess\src\Main.py", line 431, in <module>
       game1, board1 = loadgame(inp_f)
    TypeError: 'NoneType' object is not iterable
    

    NB. the call to the function is done with a string that is collected from user input "inp_f" (loadgame is the name of the function)

    Here's the code:

    try: 
        f = open(filename, "r")
        file_empty = False
    except FileNotFoundError: 
        file_empty = True
        # file doesn't exist, error string
    
    if file_empty: # empty save file, create a new game
        g, b = creategame() # this function works 100%... no problems here
    else: 
        # amount of each pieces
        tb = 0
        tn = 0
        cb = 0
        cn = 0
        fb = 0
        fn = 0
        db = 0
        dn = 0
        rb = 0
        rn = 0
        pb = 0
        pn = 0
    
        d = {} # dictionnary for the board
    
        n = 0
        f_game = ""
        f_pieces = []
        for line in f: # iterate on the file... only if file_empty == False....
            if n == 0: # first line contains general game info
                f_game = line
            else: # other lines contain coordinates of the pieces
                f_pieces += [line]
            n += 1 # increment number of lines... n-1 == number of pieces
    
        f.close() # close the file... only if the file was opened...
    
        # validating the format of the first line
        try: 
            temp1 = int(f_game[0])
            temp2 = int(f_game[2])
            temp3 = int(f_game[4])
            temp4 = int(f_game[6])
            temp5 = int(f_game[8])
            f_game = [temp1, None, temp2, None, temp3, None, temp4, None, temp5]
        except ValueError: 
            pass # display error message... bad format
    
    
        for i in f_pieces: # iterate on the list that contains information about pieces
            try: 
                i1 = int(i[0])
                i2 = int(i[1])
            except ValueError: # bad coordinates... piece is put outside the board
                i1 = 8
                i2 = 8
            if i[2] == "T": # rook
                if i[3] == "B": # white
    
                    if f_game[2] != 0 and i1 == 0 and i2 == 7: # short white roc is possible... this is the right rook, too
                        did_first_move = False
                    elif f_game[4] != 0 and i1 == 0 and i2 == 0: # long white roc is possible... and this is the right rook, too
                        did_first_move = False
                    else:  # it is not one a rook implied ina  possible roc
                        did_first_move = True
    
                    tb += 1 # increment the amount of this piece by 1
    
                    globals()["tb" + str(tb)] = Rook.Rook(0, i1, i2, did_first_move) # from the import Rook... which contains class Rook with its initializer that takes 4 args (color, line, column, first_move)
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["tb" + str(tb)] # add it to the board dictionary... key is a tuple... element is a Piece.Piece class
    
                else: # black...Rook still
    
                    if f_game[6] != 0 and i1 == 7 and i2 == 7: # short black roc possible... this is the right rook, too
                        did_first_move = False
                    elif f_game[8] != 0 and i1 == 7 and i2 == 0: # long black roc possible... this is the right rook, too
                        did_first_move = False
                    else:  # the rook is not implied in a possible roc
                        did_first_move = True
    
                    tn += 1 # increment piece type
    
                    globals()["tn" + str(tn)] = Rook.Rook(1, i1, i2, did_first_move) # once again... from the import that takes 4 args
    
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["tn" + str(tn)] # put it in the board dictionary
    
            elif i[2] == "C": # Knight
                if i[3] == "B": # white
    
                    cb += 1 # increment
                    globals()["cb" + str(cb)] = Knight.Knight(0, i1, i2) # from the import... not it takes 3 or 4 args... the last one being optional... as wether a Knight did their first move of not is irrelevant... it is not needed to pass a 4th arg
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["cb" + str(cb)] # put it in the board dictionary
    
                else: # black
                    cn += 1 # increment
                    globals()["cn" + str(cn)] = Knight.Knight(1, i1, i2) # create class instance from import...
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["cn" + str(cn)] # put it in the board dictionary
    
            elif i[2] == "F": # Bishop
                if i[3] == "B": # white
    
                    fb += 1 # increment
                    globals()["fb" + str(fb)] = Bishop.Bishop(0, i1, i2) # create class instance from import...
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["fb" + str(fb)] # put it in the board dictionary
    
                else: # black
    
                    fn += 1 # increment
                    globals()["fn" + str(fn)] = Fou.Fou(1, i1, i2) # create class instance from import...
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["fn" + str(fn)] # put it inside the board dictionary
    
            elif i[2] == "D": # Queen
                if i[3] == "B": # white
    
                    db += 1 # increment
                    globals()["db" + str(db)] = Queen.Queen(0, i1, i2) # create class instance from import...
                    if i1 < 8 and i2 < 8: # if coordinates are valid...
                        d[(i1, i2)] = globals()["db" + str(db)] # put it in the board dictionary
    
                else: # black
    
                    dn += 1 # increment
                    globals()["dn" + str(dn)] = Queen.Queen(1, i1, i2) # create class instance from import...
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["dn" + str(dn)] # put it inside the board dictionary
    
            elif i[2] == "R": # King
                if i[3] == "B": # white
    
                    if f_game[2] != 0 or f_game[4] != 0: # white king did not perform its first move
                        did_first_move = False
                    else:  # white king did move
                        did_first_move = True
    
                    rb += 1 # increment
    
                    globals()["rb" + str(rb)] = King.King(0, i1, i2, did_first_move) # create class instance from the import...
    
                    pos_r0 = (i1, i2)
    
                    if i1 < 8 and i2 < 8: # if coordinates are valid...
                        d[(i1, i2)] = globals()["rb" + str(rb)] # put it inside the board dictionary
    
                else: # black
    
                    if f_game[6] != 0 or f_game[8] != 0: # black king did not perform its first move
                        did_first_move = False
                    else:  # black king did move
                        first = True
    
                    rn += 1 # increment
    
                    globals()["rn" + str(rn)] = King.King(1, i1, i2, did_first_move) # create class instance from import...
    
                    pos_r1 = (i1, i2)
    
                    if i1 < 8 and i2 < 8: # if the coordinates are valid...
                        d[(i1, i2)] = globals()["rn" + str(rn)] # put it in the board dictionary
    
            else: # pawn
                if i[3] == "B": # white
    
                    if i1 == 1: # the pawn is still at its starting position
                        did_first_move = False
                    else: # the pawn moved from its starting position
                        did_first_move = True
    
                    pb += 1 # increment
    
                    globals()["pb" + str(pb)] = Pawn.Pawn(0, i1, i2, did_first_move) # create class instance from import
    
                    if i1 < 8 and i2 < 8: # if coordinates are valid...
                        d[(i1, i2)] = globals()["pb" + str(pb)] # put it in the board dictionary
    
                else: # black
    
                    if i1 == 1: # the pawn is still at its starting position
                        did_first_move = False
                    else: # the pawn moved from its starting position
                        did_first_move = True
    
                    pn += 1 # increment
    
                    globals()["pn" + str(pn)] = Pawn.Pawn(0, i1, i2, prem_depl) # create class instance from import...
    
                    if i1 < 8 and i2 < 8: # if coordinates are valid...
                        d[(i1, i2)] = globals()["pn" + str(pn)] # put it in the board dictionary
    
        # create the board class instance from import... which only takes 1 arg... the board itself (dict)
        b = Board.Board(d)
    
        # create the game (GameManagement class instance... from import)
        # it takes 3 optional args... number of turns since the start of the game, position of white king and position of black king...
        g = GameManagement.GameManagement(f_game[0], pos_r0, pos_r1)
    
        return g, b
    

    Edit: Hah. Thanks a lot, i was so stuck on the iteration error i did not even find this when i spent over an hour looking over everything that could cause an iteration error.

    It was just the return statement's identation.

  • justhalf
    justhalf over 10 years
    I'm a bit faster than you =p