sys.stdout.write刷新输出问题
sys.stdout.write refreshing output problem
刷新输出时,终端上写入的旧数据不会消失。
- VS 代码版本:1.37.1
- OS: Windows_NT x64 10.0.18362
from ipaddress import ip_address
import sys
import time
def ips(start, end):
start_int = int(ip_address(start).packed.hex(), 16)
end_int = int(ip_address(end).packed.hex(), 16)
return [ip_address(ip).exploded for ip in range(start_int, end_int)]
tmpList = (ips("192.168.1.254", "192.168.2.2"))
for ip in tmpList:
sys.stdout.write(f"\r{ip}")
time.sleep(2)
最后的结果是:
192.168.2.155
然而打印的列表不包含这样的数据:
[192.168.1.254, 192.168.1.255, 192.168.2.0, 192.168.2.1]
最后一个“55”来自 192.168.1.255,它不应该消失了还是我遗漏了什么?
解释:
如果您(暂时)通过“\n”(=换行)删除“\r”字符(=回车return),您将看到以下输出:
192.168.1.254
192.168.1.255
192.168.2.0
192.168.2.1
如果您使用回车 return,上一行不会自动删除,而只是打印在它上面。在这种情况下,“55”仍然在屏幕上,因为它是较早打印的并且尚未被覆盖。
解法:
一个可能的解决办法是记住上一行的长度,当下一行较短时,在该行后写上所需的空格数"erase"到前面的内容
示例:
你可以这样做(把它放在 class 而不是使用全局变量更好,但我想保持示例简短):
# instead of the last 3 lines of your code end like this:
previous_line_length = 0
def update_line(line):
global previous_line_length
required_spaces = max(0, previous_line_length - len(line))
sys.stdout.write('\r' + line + required_spaces * ' ')
previous_line_length = len(line)
for ip in tmpList:
update_line(ip)
time.sleep(1)
这是因为回车 return 字符不会删除当前行,而是将光标移动到开头并开始打印。如果您的第二个字符串小于您的第一个字符串,那么在第二个字符串打印后,第一个字符串的末尾仍将最终显示。
为确保您打印的每个字符串的长度相同,您可以使用 str.ljust
方法将您的字符串左对齐。您可以将您想要的字符串的宽度传递给 ljust
以自动正确格式化它。可选地,str.ljust
还接受另一个参数,fillchar
,它是用于填充字符串中额外 space 的字符。默认值为 space。例如,"hello".ljust(10, "x")
将 return "helloxxxxx"
.
对于标准 IPv4 地址,20 个字符的宽度已经足够 space。
将此应用于您的代码很容易:
from ipaddress import ip_address
import sys
import time
def ips(start, end):
start_int = int(ip_address(start).packed.hex(), 16)
end_int = int(ip_address(end).packed.hex(), 16)
return [ip_address(ip).exploded for ip in range(start_int, end_int)]
tmpList = (ips("192.168.1.254", "192.168.2.2"))
for ip in tmpList:
sys.stdout.write(f"\r{ip}".ljust(20)) # <--- Added call to ljust here
time.sleep(2)
刷新输出时,终端上写入的旧数据不会消失。
- VS 代码版本:1.37.1
- OS: Windows_NT x64 10.0.18362
from ipaddress import ip_address
import sys
import time
def ips(start, end):
start_int = int(ip_address(start).packed.hex(), 16)
end_int = int(ip_address(end).packed.hex(), 16)
return [ip_address(ip).exploded for ip in range(start_int, end_int)]
tmpList = (ips("192.168.1.254", "192.168.2.2"))
for ip in tmpList:
sys.stdout.write(f"\r{ip}")
time.sleep(2)
最后的结果是:
192.168.2.155
然而打印的列表不包含这样的数据:
[192.168.1.254, 192.168.1.255, 192.168.2.0, 192.168.2.1]
最后一个“55”来自 192.168.1.255,它不应该消失了还是我遗漏了什么?
解释:
如果您(暂时)通过“\n”(=换行)删除“\r”字符(=回车return),您将看到以下输出:
192.168.1.254
192.168.1.255
192.168.2.0
192.168.2.1
如果您使用回车 return,上一行不会自动删除,而只是打印在它上面。在这种情况下,“55”仍然在屏幕上,因为它是较早打印的并且尚未被覆盖。
解法:
一个可能的解决办法是记住上一行的长度,当下一行较短时,在该行后写上所需的空格数"erase"到前面的内容
示例:
你可以这样做(把它放在 class 而不是使用全局变量更好,但我想保持示例简短):
# instead of the last 3 lines of your code end like this:
previous_line_length = 0
def update_line(line):
global previous_line_length
required_spaces = max(0, previous_line_length - len(line))
sys.stdout.write('\r' + line + required_spaces * ' ')
previous_line_length = len(line)
for ip in tmpList:
update_line(ip)
time.sleep(1)
这是因为回车 return 字符不会删除当前行,而是将光标移动到开头并开始打印。如果您的第二个字符串小于您的第一个字符串,那么在第二个字符串打印后,第一个字符串的末尾仍将最终显示。
为确保您打印的每个字符串的长度相同,您可以使用 str.ljust
方法将您的字符串左对齐。您可以将您想要的字符串的宽度传递给 ljust
以自动正确格式化它。可选地,str.ljust
还接受另一个参数,fillchar
,它是用于填充字符串中额外 space 的字符。默认值为 space。例如,"hello".ljust(10, "x")
将 return "helloxxxxx"
.
对于标准 IPv4 地址,20 个字符的宽度已经足够 space。
将此应用于您的代码很容易:
from ipaddress import ip_address
import sys
import time
def ips(start, end):
start_int = int(ip_address(start).packed.hex(), 16)
end_int = int(ip_address(end).packed.hex(), 16)
return [ip_address(ip).exploded for ip in range(start_int, end_int)]
tmpList = (ips("192.168.1.254", "192.168.2.2"))
for ip in tmpList:
sys.stdout.write(f"\r{ip}".ljust(20)) # <--- Added call to ljust here
time.sleep(2)