[Python] Calling input() Multiple Times in a Thread can Cause Error in Python

Discussão em 'Python' iniciado por Stack, Outubro 2, 2024.

  1. Stack

    Stack Membro Participativo

    I wrote following python code to plot the circular motion of a point. When the matplotlib is showing the animation of the motion in the main thread, another function called get_input() is called in another thread to get input value from the user. The code is here:

    import threading
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import numpy as np

    # Initialize global variables
    user_input = 'const'
    radius = 1 # Initial radius

    # Function to handle user input in a separate thread
    def get_input():
    global user_input
    while True:
    user_input = input("Enter 'const', 'increase', or 'decrease': ")
    print(f"You entered: {user_input}")

    # Start the input thread
    input_thread = threading.Thread(target=get_input)
    input_thread.start()



    ############################################################
    # Plot Circular Motion
    ############################################################
    # Function to update the position of the point
    def update(frame):
    global radius, user_input

    # Update the radius based on user input
    if user_input == 'increase':
    radius += 0.01
    elif user_input == 'decrease':
    radius -= 0.01
    if radius < 0: # Ensure radius remains positive
    radius = 0

    # Calculate the new position of the point
    speed = np.pi / 50 # Speed of the motion
    x = radius * np.cos(frame * speed)
    y = radius * np.sin(frame * speed)

    # Update the point's position
    point.set_data(x, y)
    return point,

    # Create the figure and axis
    fig, ax = plt.subplots()
    ax.set_xlim(-2.5, 2.5)
    ax.set_ylim(-2.5, 2.5)
    ax.set_aspect('equal') # Keep the aspect ratio square
    ax.set_title("Circular Motion Animation")

    # Create a point that will move in the circle
    point, = ax.plot([], [], 'bo', markersize=10) # 'bo' means blue color, circle marker

    # Create the animation
    ani = animation.FuncAnimation(fig, update, frames=np.arange(0, 1000), interval=10, blit=True)

    # Show the animation
    plt.show()


    Once I run this, it displayed the circular motion correctly. However, when I entered some values in the command line, it shows this error:

    Enter 'const', 'increase', or 'decrease': increase
    You entered: increase
    Enter 'const', 'increase', or 'decrease': 2024-10-01 23:08:25.799 python[98112:7113683] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'nextEventMatchingMask should only be called from the Main Thread!'
    *** First throw call stack:
    (
    0 CoreFoundation 0x00000001b2f8f3f8 __exceptionPreprocess + 176
    1 libobjc.A.dylib 0x00000001b2adaea8 objc_exception_throw + 60
    2 AppKit 0x00000001b6193e14 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 2872
    3 _macosx.cpython-38-darwin.so 0x0000000106606f10 wait_for_stdin + 544
    4 python3.8 0x0000000104427fec my_fgets + 52
    5 python3.8 0x0000000104427ed8 PyOS_StdioReadline + 176
    6 python3.8 0x000000010442813c PyOS_Readline + 176
    7 python3.8 0x0000000104555e68 builtin_input_impl + 1428
    8 python3.8 0x00000001044aecf4 cfunction_vectorcall_FASTCALL + 88
    9 python3.8 0x0000000104561034 _PyEval_EvalFrameDefault + 32676
    10 python3.8 0x00000001044537ac _PyFunction_Vectorcall + 416
    11 python3.8 0x0000000104562e0c _PyEval_EvalFrameDefault + 40316
    12 python3.8 0x00000001044537ac _PyFunction_Vectorcall + 416
    13 python3.8 0x0000000104560824 _PyEval_EvalFrameDefault + 30612
    14 python3.8 0x00000001044537ac _PyFunction_Vectorcall + 416
    15 python3.8 0x0000000104560824 _PyEval_EvalFrameDefault + 30612
    16 python3.8 0x00000001044537ac _PyFunction_Vectorcall + 416
    17 python3.8 0x0000000104459758 method_vectorcall + 404
    18 python3.8 0x0000000104452cb4 PyVectorcall_Call + 472
    19 python3.8 0x0000000104636f3c t_bootstrap + 188
    20 python3.8 0x00000001045d8b58 pythread_wrapper + 48
    21 libsystem_pthread.dylib 0x00000001b2e3506c _pthread_start + 148
    22 libsystem_pthread.dylib 0x00000001b2e2fe2c thread_start + 8
    )
    libc++abi: terminating with uncaught exception of type NSException
    zsh: abort /Users/xinze/miniconda3/bin/python


    I realized that seems the problem comes from that first input() can capture my input correctly but for some reason the next input() returned immediately rather than waiting for my input. To check this, I removed the while loop in the function:

    def get_input():
    global user_input
    user_input = input("Enter 'const', 'increase', or 'decrease': ")
    print(f"You entered: {user_input}")


    and the program works (but obviously I can only input once, which is not what I want.) I'm using python 3.8.18 and the system is MacOS M1. Does anyone know how to fix this issue? Thank you!

    Continue reading...

Compartilhe esta Página