簡體   English   中英

在Python中打印tsv文件的內容(使用UTF-8)

[英]Printing contents of a tsv file (with UTF-8) in Python

我下面的代碼在名為tsv_test.py的文件中可以正常工作:

import csv

class ReadUTF8():

    def unicode_csv_reader(self, utf8_data, dialect=csv.excel_tab, **kwargs):
        csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs)
        for row in csv_reader:
            yield [unicode(cell, 'utf-8') for cell in row]


    def load_deck_data(self):
        filename = 'lexicon.tsv'
        reader = self.unicode_csv_reader(open(filename))
        for field1, field2, field3, field4 in reader:
            print field1, field2, field3, field4

ReadUTF8().load_deck_data()

但是,當我將其復制/粘貼到我的項目(這是一個奇異的項目)中時,它就會中斷。 下面的代碼和錯誤:

class StudyScreenManagement(ScreenManager):

    def unicode_csv_reader(self, utf8_data, dialect=csv.excel_tab, **kwargs):
        csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs)
        for row in csv_reader:
            yield [unicode(cell, 'utf-8') for cell in row]


    def load_deck_data(self):
        filename = 'lexicon.tsv'
        reader = self.unicode_csv_reader(open(filename))
        for field1, field2, field3, field4 in reader:
            print field1, field2, field3, field4

我懷疑這是相關的,但以防萬一,相關的.kv文件:

Button:
    text: 'Lexicon'
    on_press: app.root.load_deck_data()

輸出:

 File "/Users/bearnun/code/mingyu/mingyuKivy/mingyu_controllers.py", line 14, in load_deck_data
 for field1, field2, field3, field4 in reader:
 ValueError: need more than 1 value to unpack

::邊注::

在這兩種情況下,我都嘗試僅打印“ field1”。 更改后,兩者的輸出為:

[u'\u4b03', u'\u98d2', u'[sa4]', u'/variant of \u98af|\u98d2[sa4]/']
[u'\u4b20', u'\u4b20', u'[fei1]', u'/old variant of \u970f[fei1]/']

我想要的輸出:

䬃 颯 [sa4] /variant of 颯|颯[sa4]/
䬠 䬠 [fei1] /old variant of 霏[fei1]/

[下面的編輯]

lexicon.tsv內容:

䬃   颯   [sa4]   /variant of 颯|颯[sa4]/
䬠   䬠   [fei1]  /old variant of 霏[fei1]/

顯然,我收到的是列表而不是生成器,因此如果在load_deck_data()中,則更改:

 for field1, field2, field3, field4 in reader: print field1, field2, field3, field4 

至:

 for line in reader: print ''.join(line) 

我的項目運作良好。

看看這個例子:

data = [
    ['a', 'b', 'c', 'd'],
    ['e'],
]

def mygen(x):
    for item in x:
        yield item

for line in mygen(data):
    print ''.join(line)

--output:--
abcd
e

for col1, col2, col3, col4 in mygen(data):
    print col1, col2, col3, col4


--output:--
a b c d

Traceback (most recent call last):
  File "1.py", line 13, in <module>
    for col1, col2, col3, col4 in mygen(data):
ValueError: need more than 1 value to unpack

在第一個for-in循環中,您詢問:“請檢索列表中的所有元素並將它們連接在一起。” 在第二個forin循環中,您要求“從列表中檢索四個元素!” 看到不同? 在第一種情況下,列表可以包含0到n個元素,並且不會出現錯誤。 在第二種情況下,該列表必須至少包含4個元素-否則將出現錯誤。

我很想知道為什么要在一個地方放發電機,而在另一個地方放發電機。

簡單。 你不是 csv.reader()返回每一行的字符串列表,這意味着your generator function為每次迭代返回一個字符串列表。

我認為您更改了文件中的數據。 在一個文件中,您可以使用tab delimited數據,而csv.reader()為文件中的每一行返回一列包含四項內容的列表,可以將其解壓縮為四個變量。 但是您的其他文件具有non-tab delimited數據,這將導致csv.reader()將整行作為一項讀取,因此csv.reader()返回的字符串列表僅包含一項,而一項列表不能解壓成四個變量。

在這兩種情況下,我都嘗試僅打印“ field1”。 更改后,兩者的輸出為:

 [u'\䬃', u'\颯', u'[sa4]', u'/variant of \颯|\颯[sa4]/'] [u'\䬠', u'\䬠', u'[fei1]', u'/old variant of \霏[fei1]/'] 

我不print repr(field1) print field1 ,而是print repr(field1)我懷疑您會得到:

"[u'\u4b03', u'\u98d2', u'[sa4]', u'/variant of \u98af|\u98d2[sa4]/']"

注意外引號,這意味着您的tsv文件實際上在一行上包含以下內容:

[䬃, 颯, [sa4], /variant of 颯|颯[sa4]/]

沒有制表符分隔任何內容,因此整條看起來像列表的行作為一項讀入,因此csv.reader()返回包含該項的列表。 您被愚蠢地認為單個項目是python列表,因為當您打印字符串時,python不會顯示引號。 例如,以下兩個打印語句的輸出沒有差異:

>>> print "[1, 2, 3]"
[1, 2, 3]
>>> print [1, 2, 3]
[1, 2, 3]

在其他情況下, print也會使您不知所措,因為字符串可能包含不可打印的字符,而print的輸出不會顯示這些字符:

>>> print "hello\bworld"
hellworld

最重要的是:通過查看打印輸出,您永遠無法知道原始內容。 每當您想確切了解原始內容時,請始終使用:

print repr(some_string)

現在,看一下結果:

>>> print repr([1, 2, 3])
[1, 2, 3]
>>> print repr('[1, 2, 3]')
'[1, 2, 3]'
>>> print repr('hello\bworld')
'hello\x08world'

輸出確切地告訴您原始內容是什么。

使用以下制表符分隔的lexicon.tsv文件:

1   2   3   €
䬃   颯   [sa4]   /variant of 颯|颯[sa4]/

單擊“詞典”按鈕后,以下代碼不會導致任何錯誤:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
import csv

class StudyScreenManager(ScreenManager):

    def unicode_csv_reader(self, utf8_data, dialect=csv.excel_tab, **kwargs):
        csv_reader = csv.reader(utf8_data, dialect=dialect, **kwargs)
        for row in csv_reader:
            yield [unicode(cell, 'utf-8') for cell in row]


    def load_deck_data(self):
        filename = 'lexicon.tsv'
        reader = self.unicode_csv_reader(open(filename))
        for field1, field2, field3, field4 in reader:
            print field1, field2, field3, field4


class HistoryScreen(Screen):
    pass

class MathScreen(Screen):
    pass

class MyApp(App):
    def build(self):
        sm = StudyScreenManager()
        sm.add_widget(HistoryScreen(name='history'))
        sm.add_widget(MathScreen(name='math'))

        return sm

MyApp().run()

my.kv:

<HistoryScreen>:  #the 'root' of the following widget hierarchy:
    BoxLayout:
        Button:
            text: 'Lexicon'
            on_press: app.root.load_deck_data()  #self=Button, root=HistoryScreen, app.root=the Widget returned by build()
        Button:
            text: "Next"
            on_press: root.manager.current = "math"

<MathScreen>: #the 'root' of the following widget heirarchy:
    BoxLayout:
        Button:
            text: 'Lexicon'
            on_press: app.root.load_deck_data()
        Button:
            text: 'Previous'
            on_press: root.manager.current = "history"

單擊“詞典”按鈕后,這是我在utf-8 aware terminal window看到的輸出:

1 2 3 €
䬃 颯 [sa4] /variant of 颯|颯[sa4]/

顯然,我收到的是列表而不是生成器,所以如果在load_deck_data()中,則更改...:

for field1, field2, field3, field4 in reader:
    print field1, field2, field3, field4

...至...:

for line in reader:
    print ''.join(line)

...我的項目效果很好。 當然,這在最初起作用的小代碼段中不起作用。

我很想知道為什么要在一個地方放發電機,而在另一個地方放發電機。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM