質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

1回答

402閲覧

AttributeErrorの処理の仕方

akida

総合スコア12

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2019/03/10 10:29

###解決したいこと
https://github.com/karaage0703/TextGeneratorを参考にしてPrepareChain.pyおよびGenerateText.pyを作って、前者を実行させたところAttributeErrorが出されました。これはどう処理すればよいでしょうか

環境は
python3.6.5
windows10
です。

エラー内容

C:\Users\Desktop>python PrepareChain.py sample.txt Traceback (most recent call last): File "PrepareChain.py", line 249, in <module> chain = PrepareChain(text) File "PrepareChain.py", line 33, in __init__ text = text.decode("utf-8") AttributeError: 'str' object has no attribute 'decode'

以下実行させたPrepareChain.pyの中身です。

###PrepareChain.py

# -*- coding: utf-8 -*- r""" 与えられた文書からマルコフ連鎖のためのチェーン(連鎖)を作成して、DBに保存するファイル """ import unittest import re import MeCab import sqlite3 from collections import defaultdict import sys class PrepareChain(object): r""" チェーンを作成してDBに保存するクラス """ BEGIN = u"__BEGIN_SENTENCE__" END = u"__END_SENTENCE__" DB_PATH = "chain.db" DB_SCHEMA_PATH = "schema.sql" def __init__(self, text): r""" 初期化メソッド @param text チェーンを生成するための文章 """ if isinstance(text, str): text = text.decode("utf-8") self.text = text # 形態素解析用タガー self.tagger = MeCab.Tagger('-Ochasen') def make_triplet_freqs(self): r""" 形態素解析から3つ組の出現回数まで @return 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ # 長い文章をセンテンス毎に分割 sentences = self._divide(self.text) # 3つ組の出現回数 triplet_freqs = defaultdict(int) # センテンス毎に3つ組にする for sentence in sentences: # 形態素解析 morphemes = self._morphological_analysis(sentence) # 3つ組をつくる triplets = self._make_triplet(morphemes) # 出現回数を加算 for (triplet, n) in triplets.items(): triplet_freqs[triplet] += n return triplet_freqs def _divide(self, text): r""" 「。」や改行などで区切られた長い文章を一文ずつに分ける @param text 分割前の文章 @return 一文ずつの配列 """ # 改行文字以外の分割文字(正規表現表記) delimiter = r"。|.|." # 全ての分割文字を改行文字に置換(splitしたときに「。」などの情報を無くさないため) text = re.sub(r"({0})".format(delimiter), r"\1\n", text) # 改行文字で分割 sentences = text.splitlines() # 前後の空白文字を削除 sentences = [sentence.strip() for sentence in sentences] return sentences def _morphological_analysis(self, sentence): r""" 一文を形態素解析する @param sentence 一文 @return 形態素で分割された配列 """ morphemes = [] sentence = sentence.encode("utf-8") node = self.tagger.parseToNode(sentence) while node: if node.posid != 0: morpheme = node.surface.decode("utf-8") morphemes.append(morpheme) node = node.next return morphemes def _make_triplet(self, morphemes): r""" 形態素解析で分割された配列を、形態素毎に3つ組にしてその出現回数を数える @param morphemes 形態素配列 @return 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ # 3つ組をつくれない場合は終える if len(morphemes) < 3: return {} # 出現回数の辞書 triplet_freqs = defaultdict(int) # 繰り返し for i in xrange(len(morphemes)-2): triplet = tuple(morphemes[i:i+3]) triplet_freqs[triplet] += 1 # beginを追加 triplet = (PrepareChain.BEGIN, morphemes[0], morphemes[1]) triplet_freqs[triplet] = 1 # endを追加 triplet = (morphemes[-2], morphemes[-1], PrepareChain.END) triplet_freqs[triplet] = 1 return triplet_freqs def save(self, triplet_freqs, init=False): r""" 3つ組毎に出現回数をDBに保存 @param triplet_freqs 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ # DBオープン con = sqlite3.connect(PrepareChain.DB_PATH) # 初期化から始める場合 if init: # DBの初期化 with open(PrepareChain.DB_SCHEMA_PATH, "r") as f: schema = f.read() con.executescript(schema) # データ整形 datas = [(triplet[0], triplet[1], triplet[2], freq) for (triplet, freq) in triplet_freqs.items()] # データ挿入 p_statement = r"insert into chain_freqs (prefix1, prefix2, suffix, freq) values (?, ?, ?, ?)" con.executemany(p_statement, datas) # コミットしてクローズ con.commit() con.close() def show(self, triplet_freqs): r""" 3つ組毎の出現回数を出力する @param triplet_freqs 3つ組とその出現回数の辞書 key: 3つ組(タプル) val: 出現回数 """ for triplet in triplet_freqs: print("|".join(triplet), "\t", triplet_freqs[triplet]) class TestFunctions(unittest.TestCase): r""" テスト用クラス """ def setUp(self): r""" テストが実行される前に実行される """ self.text = r"こんにちは。 今日は、楽しい運動会です。hello world.我輩は猫である\n 名前はまだない。我輩は犬である\r\n名前は決まってるよ" self.chain = PrepareChain(self.text) def test_make_triplet_freqs(self): r""" 全体のテスト """ triplet_freqs = self.chain.make_triplet_freqs() answer = {("__BEGIN_SENTENCE__", r"今日", r"は"): 1, (r"今日", r"は", r"、"): 1, (r"は", r"、", r"楽しい"): 1, (r"、", r"楽しい", r"運動会"): 1, (r"楽しい", r"運動会", r"です"): 1, (r"運動会", r"です", r"。"): 1, (r"です", r"。", r"__END_SENTENCE__"): 1, (r"__BEGIN_SENTENCE__", r"hello", r"world"): 1, (r"hello", r"world", r"."): 1, (r"world", r".", r"__END_SENTENCE__"): 1, (r"__BEGIN_SENTENCE__", r"我輩", r"は"): 2, (r"我輩", r"は", r"猫"): 1, (r"は", r"猫", r"で"): 1, (r"猫", r"で", r"ある"): 1, (r"で", r"ある", r"__END_SENTENCE__"): 2, (r"__BEGIN_SENTENCE__", r"名前", r"は"): 2, (r"名前", r"は", r"まだ"): 1, (r"は", r"まだ", r"ない"): 1, (r"まだ", r"ない", r"。"): 1, (r"ない", r"。", r"__END_SENTENCE__"): 1, (r"我輩", r"は", r"犬"): 1, (r"は", r"犬", r"で"): 1, (r"犬", r"で", r"ある"): 1, (r"名前", r"は", r"決まっ"): 1, (r"は", r"決まっ", r"てる"): 1, (r"決まっ", r"てる", r"よ"): 1, (r"てる", r"よ", r"__END_SENTENCE__"): 1} self.assertEqual(triplet_freqs, answer) def test_divide(self): r""" 一文ずつに分割するテスト """ sentences = self.chain._divide(self.text) answer = [r"こんにちは。", r"今日は、楽しい運動会です。", r"hello world.", r"我輩は猫である", r"名前はまだない。", r"我輩は犬である", r"名前は決まってるよ"] self.assertEqual(sentences.sort(), answer.sort()) def test_morphological_analysis(self): r""" 形態素解析用のテスト """ sentence = u"今日は、楽しい運動会です。" morphemes = self.chain._morphological_analysis(sentence) answer = [r"今日", r"は", r"、", r"楽しい", r"運動会", r"です", r"。"] self.assertEqual(morphemes.sort(), answer.sort()) def test_make_triplet(self): r""" 形態素毎に3つ組にしてその出現回数を数えるテスト """ morphemes = [r"今日", r"は", r"、", r"楽しい", r"運動会", r"です", r"。"] triplet_freqs = self.chain._make_triplet(morphemes) answer = {(r"__BEGIN_SENTENCE__", r"今日", r"は"): 1, (r"今日", r"は", r"、"): 1, (r"は", r"、", r"楽しい"): 1, (r"、", r"楽しい", r"運動会"): 1, (r"楽しい", r"運動会", r"です"): 1, (r"運動会", r"です", r"。"): 1, (r"です", r"。", r"__END_SENTENCE__"): 1} self.assertEqual(triplet_freqs, answer) def test_make_triplet_too_short(self): r""" 形態素毎に3つ組にしてその出現回数を数えるテスト ただし、形態素が少なすぎる場合 """ morphemes = [r"こんにちは", r"。"] triplet_freqs = self.chain._make_triplet(morphemes) answer = {} self.assertEqual(triplet_freqs, answer) def test_make_triplet_3morphemes(self): r""" 形態素毎に3つ組にしてその出現回数を数えるテスト ただし、形態素がちょうど3つの場合 """ morphemes = [r"hello", r"world", r"."] triplet_freqs = self.chain._make_triplet(morphemes) answer = {(r"__BEGIN_SENTENCE__", r"hello", r"world"): 1, (r"hello", r"world", r"."): 1, (r"world", r".", r"__END_SENTENCE__"): 1} self.assertEqual(triplet_freqs, answer) def tearDown(self): r""" テストが実行された後に実行される """ pass if __name__ == '__main__': # unittest.main() param = sys.argv if (len(param) != 2): print ("Usage: $ python " + param[0] + " sample.txt") quit() f = open(param[1], encoding='utf-8') text = f.read() f.close() # print (text) chain = PrepareChain(text) triplet_freqs = chain.make_triplet_freqs() chain.save(triplet_freqs, True)

32~34行目が

32 if isinstance(text, str): 33 text = text.decode("utf-8") 34 self.text = text

243~251行目が

243 f = open(param[1], encoding='utf-8') 244 text = f.read() 245 f.close() 246 247 # print (text) 248 249 chain = PrepareChain(text) 250 triplet_freqs = chain.make_triplet_freqs() 251 chain.save(triplet_freqs, True)

となっています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

元がpython2のコードっぽいですね。__init__内のif文を消してしまって構いません。

python

1 def __init__(self, text): 2 r""" 3 初期化メソッド 4 @param text チェーンを生成するための文章 5 """ 6 self.text = text 7 8 # 形態素解析用タガー 9 self.tagger = MeCab.Tagger('-Ochasen')

他にも修正箇所はいろいろありそうで、python2とpython3の文字列処理の違いを把握していないと修正できないと思います。回答で説明しようとも思ったけど、途中まで書いて面倒くさいことに気づいたのでパス。「python2 python3 文字列 違い」とかで検索すればたくさん解説が出てくるので、それを読んでください。

投稿2019/03/10 12:23

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問