Python 如何使用诅咒在终端中写入三个不断更新的行?
我有一个程序,需要输出三条不断变化的信息。连接数、经过的时间和拒绝的连接 我尝试在字符串末尾使用Python 如何使用诅咒在终端中写入三个不断更新的行?,python,curses,Python,Curses,我有一个程序,需要输出三条不断变化的信息。连接数、经过的时间和拒绝的连接 我尝试在字符串末尾使用'\r'编写它们,并在其他行开始它们自己的输出循环之前打印换行符,认为回车符返回一行。但它们最终都在第一行相互覆盖 我看到过类似的问题,人们建议使用诅咒,但我似乎无法让它发挥作用。我尝试使用addstr()而不是print或sys.stdout.write(),但显然我做得不对,因为它看起来就像我也尝试过使用move(0,0)在每次addstr之后,因为我认为坐标可能是从光标的最后一个位置计算出来的,
'\r'
编写它们,并在其他行开始它们自己的输出循环之前打印换行符,认为回车符返回一行。但它们最终都在第一行相互覆盖
我看到过类似的问题,人们建议使用诅咒
,但我似乎无法让它发挥作用。我尝试使用addstr()
而不是print
或sys.stdout.write()
,但显然我做得不对,因为它看起来就像我也尝试过使用move(0,0)
在每次addstr
之后,因为我认为坐标可能是从光标的最后一个位置计算出来的,但输出看起来与我没有这样做时一样
以下是我当前使用的诅咒的代码
-
from scapy.all import *
from curses import wrapper
import argparse, random, socket, sys, time, os, threading, re, subprocess, curses
def main(target):
try:
stdscr.clear()
curses.noecho()
curses.cbreak()
stdscr.keypad(1)
#things regarding user agents and iptables
for conn in range(args.connections):
t = threading.Thread(target=sendPacket, args=(targetIP, args.port, targetHost,random.choice(userAgents)))
threads.append(t)
t.start()
numConn += 1
try:
lock.acquire()
stdscr.addstr(0, 0,'{0} Connections Established to {1} '.format(numConn,getIP(target)))
stdscr.refresh()
#sys.stdout.flush()
finally:
lock.release()
time.sleep(args.timer)
CloseWin()
sys.exit()
except KeyboardInterrupt, e:
lock.acquire()
stdscr.addstr (5,0,'Exiting {0}'.format(e))
CloseWin()
lock.release()
sys.exit()
#functions that deal with resolving host and IP
def sendPacket(targetIP,targetPort,targetHost,userAgent):
try:
#building and sending the packet
failPacket = 0
lock.acquire()
if synack is None:
stdscr.addstr(1, 0, '{0} Connections refused'.format(failPacket))
stdscr.refresh()
failPacket += 1
return
#send final packet
lock.release()
return
except Exception,e:
CloseWin()
#print e
lock.release()
return
def MeasureTime():
try:
lock.acquire()
while True:
stdscr.addstr(3, 0,'{0} Time elapsed'.format(time.time() - startTime))
stdscr.refresh()
finally:
lock.release()
def CloseWin():
try:
lock.acquire()
curses.nocbreak()
stdscr.keypad(0)
curses.echo()
curses.endwin()
finally:
lock.release()
if __name__ == '__main__':
#args
stdscr = curses.initscr()
if args.debug == True:
wrapper(OneConn(args.target)) #OneConn is the same as the main function except it only opens one connection, so the print is the same
else:
startTime = time.time()
wrapper(main(args.target))
此外,除了写得不正确之外,我似乎无法正确地关闭它,当我使用ctrl+c
尝试退出时,它似乎停止更新有关数据包的打印输出,但时间仍在继续。我除了关闭终端之外,也找不出办法阻止它
根据@martinaeu的建议尝试添加锁,并编辑了帖子以展示我所做的。结果是,我只能看到第四行中打印和更新的
时间,根本看不到其他打印,并且在不关闭终端的情况下仍然无法退出程序而不是使用curses
,您只需发出原始代码将光标向后移动三行即可。这将是:
os.write(1, "\x1b[3F")
小心:这些线没有被擦掉。如果打印的新行的长度与旧行的长度相同(例如,因为它们的格式类似于“foo:%10d”
)
参考:(其中“CSI”代表“\x1b[”,n是一个十进制可选数字)。至少您遇到的一些问题可能与多线程有关,因为有多个线程试图同时使用诅咒(至少在逻辑上)。若要同时成功使用它,您可能需要添加一个锁
对象,使每个线程(包括主线程)必须在使用诅咒API之前获取并在之后发布。@martineau以前从未使用过锁,所以我仔细阅读了它们,并尝试以我认为有意义的方式添加它们。编辑了主要帖子以反映您使用Lock()的方式
效率有点低,在线程化的sendPacket()
函数中使用它的方式可能有一个小错误。建议您多读一点关于它们的内容,并开始通过with
语句将它们用作上下文管理器。这将消除大部分(如果不是全部的话)的需要,最后尝试/一些东西(因为with
将确保调用release()
,无论是否存在异常,即使有多个return
语句)。至于最初的问题,我认为addstr()的位置参数
是相对于他们将输出发送到的屏幕的一角,这意味着每个sendPacket
线程都需要在不同的行上添加/更新信息,以使它们都可见。您可以将行传递给他们(这里实际上不需要列)创建每个线程时,将其定位为函数的附加参数。@martineau我希望sendPacket
将其全部写入一行,只需更改发送的数据包数即可。一开始我认为addstr()
是相对于屏幕的一角,我认为我调用这些行的方式是有意义的,但它似乎不起作用。关于lock()
,我是否只是将所有try/finally
内容替换为with lock: