Minimum path sum in a triangle (Project Euler 18 and 67) with Python
General

Since the problem gives the triangle as a text file, your program should probably be able to read that file. It would be quite a lot of work to input them manually, and when using the file like in python triangle.py &lt; triangle.txt a first row with the number of lines needs to be added. This reading function can be quite simple:

def read_triangle(file_name):
    with open(file_name) as f:
        return [list(map(int, line.split())) for line in f]


Algorithm

As for the actual algorithm, I'm not quite sure what yours does. Which means that it is not very readable :). Not having any documentation, like a docstring does not help either.

The easiest algorithm for this is a bottom up approach that reduces each line into the maximum sum reachable from the line above it.

def reduce_rows(row, row_below):
    """Reduces two consecutive rows to the maximum reachable sum from the top row."""
    return [max(row_below[i], row_below[i+1]) + row[i] for i in range(len(row))]

def max_sum(triangle):
    """Find the maximum sum reachable in the triangle."""
    row_below = triangle.pop()
    for row in reversed(triangle):
        row_below = reduce_rows(row, row_below)
        # print(row_below)
    return row_below[0]

if __name__ == "__main__":
    triangle = read_triangle("triangle.txt")
    print(max_sum(triangle))


Style

It's a good thing that you are already using a if __name__ == "__main__": guard. You also seem to be mostly following Python's official style-guide, PEP8. The only thing you could improve on that part is to reduce the number of blank lines. While some help the readability, parts that are logically connected should be in one block:

height = None
while True:
    try:
        height = int(input('Please enter height of the triangle: '))
        if height &lt;= 0:
            raise Exception('Height cannot be negative or 0')
        break
    except Exception as e:
        print(f'Error occurred: {e}\n')

triangle = []
for row_index in range(1, height + 1):
    while True:
        try:
            row = list(map(int, input(f'Please enter {row_index} space seperated integer(s): ').split()))
            if len(row) != row_index:
                raise Exception(f'Exactly {row_index} numbers required')
            elif any(number &lt; 0 for number in row):
                raise Exception(f'Numbers cannot be negative')
            else:
                triangle.append(row)
                break
        except Exception as e:
            print(f'Error occurred: {e}\n')


I also put the separate exceptions and the happy path into an if..elif..else structure. This is not really needed (the other cases are never reachable if an exception is raised), but IMO it helps with readability. It also make it easier if at some point you decide that those should just print a message directly, instead of raising an exception that is immediately caught only to be printed. You could make those print statements directly, which would allow you to be more specific about the exception you expect. This makes it so that all other exceptions stop the program (as they should):

while True:
    try:
        height = int(input('Please enter height of the triangle: '))
    except ValueError as e:
        print(f'Error occurred: {e}\n')
    if height &gt; 0:
        break
    else:
        print('Error occurred:  Height cannot be negative or 0')

triangle = []
for row_index in range(1, height + 1):
    while True:
        try:
            row = list(map(int, input(f'Please enter {row_index} space separated integer(s): ').split()))
        except ValueError as e:
            print(f'Error occurred: {e}\n')
        if len(row) != row_index:
            print(f'Error occurred:  Exactly {row_index} numbers required')
        elif any(number &lt; 0 for number in row):
            print(f'Error occurred:  Numbers cannot be negative')
        else:
            triangle.append(row)
            break


Better user input

This is actually a good place to implement a function asking for user input and validating it. We need type validation and input validation here, so this should suffice:

def ask_user(message, type_=str, validate=None, non_valid_msg=""):
    while True:
        try:
            user_input = type_(input(message))
        except ValueError as e:
            print(f"Expected {type_}")
            continue
        if validate is not None:
            if validate(user_input):
                return user_input
            else:
                print(non_valid_msg)
        else:
            return user_input


Which makes your code a lot easier:

def list_of_int(s):
    return list(map(int, s.split()))

if __name__ == "__main__":
    height = ask_user("Please enter height of the triangle: ", int,
                      lambda h: h &gt; 0, "Height must be positive")
    triangle = [ask_user(f"Please enter {n} space separated integer(s): ", list_of_int,
                         lambda l: len(l) == n, f"Exactly {n} numbers required")
                for n in range(1, height + 1)]
    ...