Вам необходимо вручную построить строку, а также вручную построить длину формата.Для этого нет простого способа
Три функции, перечисленные ниже, делают это (требуется unicodedata):
shortenStringCJK: правильно сокращать до длины для подгонки в некоторых выходных данных (без сокращения длины для получения символов X))
def shortenStringCJK(string, width, placeholder='..'):
# get the length with double byte charactes
string_len_cjk = stringLenCJK(str(string))
# if double byte width is too big
if string_len_cjk > width:
# set current length and output string
cur_len = 0
out_string = ''
# loop through each character
for char in str(string):
# set the current length if we add the character
cur_len += 2 if unicodedata.east_asian_width(char) in "WF" else 1
# if the new length is smaller than the output length to shorten too add the char
if cur_len <= (width - len(placeholder)):
out_string += char
# return string with new width and placeholder
return "{}{}".format(out_string, placeholder)
else:
return str(string)
stringLenCJK: получить правильную длину (как в пространстве, занимаемом терминалом)
def stringLenCJK(string):
# return string len including double count for double width characters
return sum(1 + (unicodedata.east_asian_width(c) in "WF") for c in string)
formatLen: отформатировать длину, чтобы настроить ширину из двухбайтовых символов.без этого длина будет несбалансированной.
def formatLen(string, length):
# returns length udpated for string with double byte characters
# get string length normal, get string length including double byte characters
# then subtract that from the original length
return length - (stringLenCJK(string) - len(string))
для вывода некоторой строки: предварительно определите строку формата
format_str = "|{{:<{len}}}|"
format_len = 26
string_len = 26
и выведите ее следующим образом (где _string - строка для вывода)
print("Normal : {}".format(
format_str.format(
len=formatLen(shortenStringCJK(_string, width=string_len), format_len))
).format(
shortenStringCJK(_string, width=string_len)
)
)