Basic Collatz program with input validation in Python
Most of your code deals with obtaining and validating user input. That's
tedious code to write and maintain. In addition, programs premised on
user-interactivity are difficult to execute during development, testing, and
debugging: every execution requires a manual dialogue between the user (you,
the programmer) and the computer. That get annoying very fast. Moreover, your
program provides no clean way to quit. A more powerful approach based on
command-line arguments and the built-in argparse library is shown below.
The second issue is that your collatz() function intermixes algorithmic
computation and reporting (i.e. printing). That's almost
always a bad idea. A more flexible approach is to restrict collatz() purely to
the algorithm and do the printing at a higher level in the program -- either in
main(), if the reporting remains extremely simple, or in a function called by it.
The essence of most of these suggestions is to organize your code more
carefully to keep different tasks more separated: user input collection; input
validation; computation; and reporting.
import argparse
import sys

def main(args):
    # Get user arguments.
    opts = parse_args(args)

    # Make computations.
    sequences = [list(collatz(val)) for val in opts.initial_values]

    # Report to user. Enhance as needed.
    for seq in sequences:
        print(seq)

def parse_args(args):
    # You want the user to provide one or more integers
    # on the command line. The argparse library will handle that
    # automatically for many use cases (e.g, any integer). In your situation,
    # you do need to write a type validation function, but that process
    # is a bit simpler and more focused than your previous validation
    # code, which was mixed with the rest of the program's logic.
    ap = argparse.ArgumentParser()
    ap.add_argument('initial_values', nargs = '+', type = positive_int)
    return ap.parse_args(args)

def positive_int(val):
    # You can make this more robust if needed (eg to prevent values like
    # '12.34' from being accepted), but here's the basic technique.
    try:
        n = int(val)
        1 / n
        return n
    except Exception:
        raise argparse.ArgumentTypeError(f'Invalid positive integer: {val}')

def collatz(n):
    # Relieved of printing, this function becomes simpler, more testable,
    # and more general purpose.
    while n &gt; 1:
        yield n
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1
    yield n

# Invoke main() if the program was executed rather than imported.
# This is important for testability, because testing tools need
# to import your code without executing the script in its entirety.
if __name__ == '__main__':
    main(sys.argv[1:])