[英]Python TSV File Parsing and UTF-8 Output Errors (TypeError: 'str' object is not callable)
[英]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.