Python - 将用户输入框保留在上面,在 while 循环中不断打印文本

问题描述 投票:0回答:1

我正在尝试编写一个Python程序,该程序在后台循环程序并等待用户输入,在循环中执行操作或退出循环。代码分为三个主要部分:

  • 程序不断运行并绘制温度和 pH 值(这在线程中运行)
  • 用于执行频率读数的程序(通过用户在输入中输入“FREQ”来激活)
  • 退出循环并关闭线程(由用户在输入中输入“EXIT”激活)

我遇到的问题是我想将用户输入框保留在循环打印温度和 pH 值的连续打印上方。

我尝试重新安排线程启动的时间以及用户输入出现的位置,但看起来线程需要位于检查用户输入的 while 循环之上。因此,如果在输入框中输入了某些内容,它将开始将输入框放置在最近的打印语句下方(这很难跟踪)。我也尝试过使用显示器(来自 IPython.display),但不确定是否可以初始化显示器并将用户输入框放入此显示器中以保持在打印语句之上。

下面的代码是我到目前为止所拥有的,但用户输入最终打印的结果低于最新的温度和 pH 文本打印输出。

import threading
import time
from IPython.display import display, clear_output

# FUNCTIONS

def freq_sweep():
    print('-------freq sweep STARTED')
    time.sleep(5)
    print('-------freq sweep FINISHED')

def temp_pH_reading_plotting():
    print(f"Temp: 100, pH: 10")
    time.sleep(1)

def run_loop():
    global stop_loop
    while not stop_loop:
        
        temp_pH_reading_plotting()
        
        if stop_loop:
            break

# MAIN CODE

# Define a global variable to control the loop
stop_loop = False

# Create a thread for the loop
loop_thread = threading.Thread(target=run_loop)
loop_thread.start()

# Listen for user input
while True:
    user_input = input("Enter 'EXIT' to stop the loop or 'FREQ' to do a frequency sweep: ")

    if user_input == 'EXIT':
        stop_loop = True
        print("Exiting program...")
        break
    elif user_input == 'FREQ':
        freq_sweep()


# Wait for the loop thread to finish
loop_thread.join()
print("Program has ended.")

下图是当文本框中没有输入任何内容时代码如何启动的,我想保持这种方式。

但是每当输入文本时,用户输入就会开始打印在最近的打印语句下方,如下所示:

请注意,代码确实可以激活频率扫描(如图 2 所示),并且可以在用户输入框中输入“EXIT”时退出代码,但输入框不会停留在一处。

非常感谢任何有关如何解决此问题的想法或建议!

python multithreading user-input python-multithreading
1个回答
0
投票

您可以尝试使用像tqdm这样的库。 这里有一个如何并行写入多行的示例:https://github.com/tqdm/tqdm/blob/master/examples/parallel_bars.py

并行更新行的一个简单示例是:

import time
import random
import string
from threading import Thread
from collections import deque
from tqdm import tqdm


sensor_data = deque()

def fetch_sensor_data(sensor_data):
    while True:
        # simulate fetching some data
        time.sleep(1)
        random_string = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
        sensor_data.append(random_string)

sensor_thread = Thread(target=fetch_sensor_data, args=(sensor_data,))
sensor_thread.start()

first_bar = tqdm(None, bar_format='{desc}')
second_bar = tqdm(None, bar_format='{desc}')

def display_lines(sensor_data, first_bar, second_bar):
    while True:
        if len(sensor_data):
            first_bar.set_description_str(f'Top line: {sensor_data.popleft()}')
        random_value = random.randint(1,1000)
        if random_value % 10 == 0:
            second_bar.set_description_str(f"Static text before -- {random_value} -- Static text after")
        time.sleep(0.1)


display_thread = Thread(target=display_lines, args=(sensor_data, first_bar, second_bar))
display_thread.start()

您也可以使用

'\033[A'
,因为这会告诉终端向上一行。您可以在这里找到一些有用的信息:https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html

- Position the Cursor:
  \033[<L>;<C>H
     Or
  \033[<L>;<C>f
  puts the cursor at line L and column C.
- Move the cursor up N lines:
  \033[<N>A
- Move the cursor down N lines:
  \033[<N>B
- Move the cursor forward N columns:
  \033[<N>C
- Move the cursor backward N columns:
  \033[<N>D
- Clear the screen, move to (0,0):
  \033[2J
- Erase to end of line:
  \033[K
- Save cursor position:
  \033[s
- Restore cursor position:
  \033[u
© www.soinside.com 2019 - 2024. All rights reserved.