Python форматирование строк с переносами строк - PullRequest
1 голос
/ 27 октября 2011

Я пытаюсь отформатировать некоторые текстовые данные из базы данных для отправки по электронной почте в Django. Я сталкиваюсь с некоторыми проблемами со строками с переносами строк.

В частности, мой желаемый вывод:

1)  t1                     t2
    t1_continue            t2_end
    t1_end

2)  s1                     s3
    s1_continue
    s1_end

Здесь строки, взятые из базы данных: "t1 \ nt1_continue \ nt1_end", "t2 \ nt2_end", "s1 \ ns1_continue \ ns1_end" и "s3".

Этот желаемый результат похож на то, что мы видим, если у нас есть 3 столбца в Excel.

Что я хочу сказать, так это то, что некоторые строки содержат разрывы строк с таким простым форматированием, как:

print str(index) + '\t' + col1 + '\t' + col2 

не будет работать.

Пожалуйста, поделитесь со мной своим подходом.

Большое спасибо.

Ответы [ 4 ]

3 голосов
/ 27 октября 2011

Способ отображения \t зависит от ОС, приложения и т. Д. Для правильного форматирования строки я бы порекомендовал проверить docs . Для вашего примера

print('{0})  {1:<25} {2}'.format(index,col1,col2))

Будет делать то, что вы хотите, предполагая, что col1 никогда не превышает 24 символов. Если это так, вы всегда можете настроить это значение по своему вкусу.

1 голос
/ 28 октября 2011

Я думал, что смогу взломать что-нибудь вместе за несколько минут, но форматирование текста в столбцы сложнее, чем я думал. Однако вот что я получил до сих пор, все еще довольно глючный ...

class format_lines(object):
    """
    1)  some text goes      2nd column of text
        here. But not       its not really that
        all text goes       hard to add more text
        in this column      in a given format

    2)  another point
        for text
    """

    def __init__(self, *args, **kargs):
        self.max_char_width = 30
        self.gutter_width = 15
        self.gutter = ' '*self.gutter_width
        self.previous_line1 = None
        self.previous_line2 = None
        self.p1_index = 0
        self.p2_index = 0
        print args
        print "len args = ", len(args)
        if len(args) == 2:
            print "Starting the test"
            self.print_lines_(args[0], args[1])

    def print_lines_(self, p1, p2):
        while self.p1_index < len(p1.split()): 
            this = self.format_line_(p1, p2)
            p1=this['p1']
            p2=this['p2']
            print this['line']

    #problem with this format is it's going to messup words by
    #pushing them to the next line (this could be fixed with a -
    #or this function could be rewritten
    def format_line_(self, p1, p2):
        #must first figure out amount of words that can fit on a line
        p1_words = [""]
        p2_words = [""]
        if p1:
            p1_words = p1.split(' ')
            p1_words = p1_words[self.p1_index:]
        if p2:
            p2_words = p2.split(' ')
            p2_words = p2_words[self.p2_index:]
        #format left side's output
        loutput = p1_words[0]
        if len(loutput) < self.max_char_width:
            for i, word in enumerate(p1_words[1:]):
                if (len(loutput) + len(word)) <= self.max_char_width:
                    loutput += (' {0}'.format(word))
                    self.p1_index = i
                else:
                    break
            self.p1_index+=1 #for loop iteration starts at index 1 not 0 so
                        #a +1 is required
        elif (len(loutput) > self.max_char_width):
            long_word = []
            long_word.append(loutput[:len(loutput)/2])
            long_word.append(loutput[len(loutput)/2:])
            long_word[0]+='-'
            p1_words[0]=long_word[0]
            p1_words.insert(1, long_word[1])
            p1 = ' '.join(p1_words)
        else:
            #the left output is a single word
            #equal to the max_char_width
            pass
        #need to add 1 to the index, because at least 1 element in the list is
        #going to be printed
        self.p1_index+=1
        #format right side's output
        routput = p2_words[0]
        if len(routput) < self.max_char_width:
            for word in p2_words[1:]:
                if (len(routput) + len(word)) <= self.max_char_width:
                    routput += (' {0}'.format(word))
                else:
                    break
            self.p2_index+=1
        elif len(routput) > self.max_char_width:
            long_word = []
            long_word.append(routput[:len(routput)/2])
            long_word.append(routput[len(routput)/2:])
            long_word[0]+='-'
            p2_words[0]=long_word[0]
            p2_words.insert(1, long_word[1])
            p2 = ' '.join(p2_words)
        else:
            #the right output is a single word
            #equal to the max_char_width
            pass
        self.p2_index+=1

        #determin gutter size
        if len(loutput) < self.max_char_width:
            loutput+=(' '*(self.max_char_width-len(loutput)))
        #do not need to append spaces to the right hand size

        output = ''
        #if previous_line1 is not defined then there should be no way that previous_line2 is defined
        if not self.previous_line1:
            #must be the first line of a bullet point
            output = '1){0}{1}{2}{3}'.format(self.gutter,
                                             loutput,
                                             self.gutter,
                                             routput)
            self.previous_line1 = loutput
            self.previous_line2 = routput
        else:
            p1_width = len(self.previous_line1)
            p2_width = len(self.previous_line2)
            if loutput<p1_width:
                loutput+=(' '*(len(self.previous_line1)-p1_width))
            if routput<p2_width:
                routput+=(' '*(len(self.previous_line2)-p2_width))
            output = '  {0}{1}{2}{3}'.format(self.gutter,
                                             loutput,
                                             self.gutter,
                                             routput)
        ret_val = {'line':output, 'p1':(' '.join(p1_words)), 'p2':(' '.join(p2_words))}
        return ret_val

if __name__ == '__main__':
    t1 = "this is a very long line of text much larger than you can fit on one line"
    t2 = "this is another long line, only this line is a little different from the first line"
    test = format_lines(t2, t1)
1 голос
/ 27 октября 2011

Вы можете использовать <table> для отображения табличных данных в теле письма.

Перед циклом, print s для каждой строки таблицы, print заголовок таблицы:

print('<table>')

Для каждой строки данных отформатируйте ее следующим образом:

print('<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>'.format(index, col1, col2))   

Наконец, после цикла, который print s каждой строки таблицы, print нижний колонтитул таблицы:

print('</table>')
0 голосов
/ 27 октября 2011

Мне кажется, я понимаю, о чем вы спрашиваете. Вы хотите обернуть текст в столбец, как в Excel, если у вас есть блок текста в ячейке. Я думаю этот рецепт поможет вам начать; Похоже, он делает то, что вы хотите.

...