TicTacToe between Gandalf and Saruman
Coding style

There's a limit to how much untidiness a reviewer is willing to tolerate.
This code is right on the border.
Please read PEP8 and follow the recommendations carefully.
There is also a command line utility called pep8 that can check your program and tell you what to fix.
There are also editors like PyCharm that warn you about violations of coding conventions,
and help you fix them.

In my review below, I will try to not repeat what PEP8 can already tell about your code.

Return values

Many of the functions don't have an explicit return value.
Take for example this:


def checkVertical(table,token):
        # VERTICAL
        for column in zip(*table):
            check_col = []
            for item in column:
                if item == token:
                    check_col.append(token)
                if len(check_col) == len(table[0]):
                    return True



The nested loop might be exited with a return True.
If that doesn't happen,
there's no other return statement,
so the method will exit with None.
This may work OK,
as None is a falsy value in Python,
but it would be cleaner to add a return False at the end to make this a proper boolean function.

Strange logic

What is going on in this function?


def whoWon(who, table, token):
    if who == 'x':
        if(checkHorizontal(table,token)): return True
        elif(checkVertical(table,token)): return True
        elif(checkDiagonal(table,token)): return True
    else:
        if(checkHorizontal(table,token)): return True
        elif(checkVertical(table,token)): return True
        elif(checkDiagonal(table,token)): return True



Regardless of the value of who,
the same code gets executed.
And again, there's no explicit return statement in case none of the conditions match.
As it is, the function could be replaced with:

def whoWon(who, table, token):
    return checkHorizontal(table, token) or checkVertical(table, token) or checkDiagonal(table, token)


Separation of concerns

The board() function reads the board size and initializes a board.
That's two distinct responsibilities.
It would be better to split these to different functions.

Simplifications

The initialization of the board in the board() function can be simplified:

return [[0] * board_size for _ in range(board_size)]


checkHorizontal() can be similarly simplified:

def checkHorizontal(table, token):
    for row in table:
        if all(column == token for column in row):
            return True
    return False