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

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

ただいまの
回答率

87.37%

sre_constans.error: nothing ti repeat at position 0 のエラーが分かりません

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 4,344

score 5

前提・実現したいこと

pythonでAIを作っています。tkinterを使ってチャットなどを出しているのですが、会話のテンプレート用の辞書を作成しプログラムを組んだのですが、エラーがさっぱりわかりません。 エラーを調べてみたのですが、全く出てきませんでした。

発生している問題・エラーメッセージ

イメージ説明

該当のソースコード

import random
import re
from analyzer import *

class Dictionary:
    def __init__(self):
        self.random = [] # (1)
        # ランダム辞書ファイルオープン
        rfile = open('dics/random.txt', 'r', encoding = 'utf_8')
        # 各行を要素としてリストに格納
        r_lines = rfile.readlines()
        rfile.close()

        # 末尾の改行と空白文字を取り除いて
        # インスタンス変数(リスト)に格納
        for line in r_lines:
            str = line.rstrip('\n')
            if (str!=''):
                self.random.append(str)
        # 辞書を保持
        self.pattern = []
        # パターン辞書オープン
        pfile = open('dics/pattern.txt', 'r', encoding = 'utf_8')
        # 各行を要素としてリストに格納
        p_lines = pfile.readlines()
        pfile.close()
        # 末尾の改行と空白文字を取り除いて
        # インスタンス変数(リスト)に格納
        self.new_lines = []
        for line in p_lines:
            str = line.rstrip('\n')
            if (str!=''):
                self.new_lines.append(str)

        # 辞書をタブで分ける
        # ptn 正規表現
        # prs 応答例
        # ParseItemオブジェクトを生成(引数はptn、prs)して
        # インスタンス変数pattern(リスト)に追加
        for line in self.new_lines:
            ptn, prs = line.split('\t')
            self.pattern.append(ParseItem(ptn, prs))

        # テンプレート辞書を保持
        self.temp = {}
        # パターン辞書ファイルオープン
        tfile = open('dics/temp.txt', 'r', encoding = 'utf_8')
        # 要素をリストに格納
        t_lines =tfile.readlines()

        #print(t_lines)
        tfile.close()
        #末尾の改行を無くし 変数(リスト)に格納
        self.new_t_lines = []
        for line in t_lines:
            str = line.rstrip('\n')
            if (str!=''):
                self.new_t_lines.append(str)
            #print(self.new_t_lines)

        # 辞書の行をタブで分ける
        # count     %noun%の出現回数
        for line in self.new_t_lines:
            # テンプレート行をタブでcount, templateに分ける
            count, temp = line.split('\t')
            # countがされない場合 空のリストに追加
            if not count in self.temp:
                self.temp[count] = []
            # countのリストにtempの文字列を追加
            self.temp[count].append(temp)

    def study(self, input, parts):
        # インプット文字列の末尾の改行
        input = input.rstrip('\n')
        self.study_random(input)
        self.study_pattern(input, parts)
        self.study_temp(parts)

    def study_random(self, input):
        # 発言を学習する
        # ランダム辞書に存在しない場合 selfで追加
        if not input in self.random:
            self.random.append(input)

    def study_pattern(self, input, parts):
        # ユーザーの発言を学習する
        # 2つのパラメーターにリストの要素を取り出す
        for word, part in parts:
            # Trueの場合
            if (keyword_check(part)):
                depend = False # ParseItemオブジェクトを保持
                # 反復処理
                for ptn_item in self.pattern:
                    m = re.search(ptn_item.pattern, word)
                    # 元々あるパターンなら
                    # リストからParseItemオブジェクトを取得
                    if(re.search(ptn_item.pattern, word)):
                        depend = ptn_item
                        break   #マッチしたら止める
                # 元々あるパターンとマッチしたParseItemオブジェクトから
                # add_phraseを呼ぶ
                if depend:
                    depend.add_phrase(input) # インプット文字列
                else:
                    # パターンに存在しない名詞であれば
                    # ParseItemオブジェクトにpatternリストに追加
                    self.pattern.append(ParseItem(word, input))

    def study_temp(self, parts):
        temp = ''
        count = 0
        for word, part in parts:
            # 名詞であるか確認
            if (keyword_check(part)):
                word = '%word%'
                count += 1
            temp += word

        # self.tempにcountが無ければ
        # countを空のリストに追加
        if count > 0:
            count = str(count)

            if not count in self.temp:
                self.temp[count] = []
            # countのリストに文字列を追加
            if not temp in self.temp[count]:
                self.temp[count].append(temp)

    def save(self):
        """ self.randomの内容をまるごと辞書に書き込む
        """
        # 各要素の末尾に改行を追加
        for index, element in enumerate(self.random):
            self.random[index] = element +'\n'
        # ランダム辞書に書き込む
        with open('dics/random.txt', 'w', encoding = 'utf_8') as f:
            f.writelines(self.random)

            # 辞書にデータを保持
            pattern = []
            for ptn_item in self.pattern:
               # make_line()で行データ作成
               pattern.append(ptn_item.make_line() + '\n')

            # パターン辞書ファイルに書き込む
            with open('dics/pattern.txt', 'w', encoding = 'utf_8') as f:
                 f.writelines(pattern)

            temp = []
            # self.templateのすべての値を取得し反復処理を行う
            for key, val in self.temp.items():
                for v in val:
                    temp.append(key + '\t' + v + '\n')
            # リスト内のテンプレートを読み込み
            temp.sort()
            # テンプレ辞書に書き込む
            with open('dics/temp.txt', 'w', encoding = 'utf_8') as f:
                f.writelines(temp)
class ParseItem:
    SEPARATOR = '^((-?\d+)##)?(.*)$'

    def __init__(self, pattern, phrases):
        """ @param pattern  パターン
            @param phrases  応答例
        """
        # 辞書のパターンの部分にSEPARATORをパターンマッチさせる
        m = re.findall(ParseItem.SEPARATOR, pattern)
        # インスタンス変数modifyに0を代入
        self.modify = 0
        # マッチ結果の整数の部分が空でなければ値を代入
        if m[0][1]:
          self.modify =int(m[0][1])
        # インスタンス変数patternにマッチ結果のパターン部分を代入
        self.pattern = m[0][2]

        self.phrases = []   # 応答例を保持するインスタンス変数
        self.dic = {}       # インスタンス変数
        # 引数で渡された応答例を'|'で分割し、
        # 個々の要素に対してSEPARATORをパターンマッチさせる
        # self.phrases[ 'need'  : 応答例の整数部分
        #               'phrase': 応答例の文字列部分 ]
        for phrase in phrases.split('|'):
            # 応答例に対してパターンマッチを行う
            m = re.findall(ParseItem.SEPARATOR, phrase)
            # 整数部分m[0][1]にする
            # 応答文字列m[0][2]にする
            self.dic['need'] = 0
            if m[0][1]:
                self.dic['need'] = int(m[0][1])
            self.dic['phrase'] = m[0][2]
            # 作成した辞書をphrasesリストに追加
            self.phrases.append(self.dic.copy())

    def match(self, str):
        """self.pattern(各行ごとの正規表現)を
           インプット文字列にパターンマッチ
        """
        return re.search(self.pattern, str)

    def choice(self, mood):
        """インスタンス変数phrases(リスト)の
           要素('need''phrase'の辞書)
            'need':数値を

            @ptam mood 現在の機嫌値
        """
        choices = []
        # self.phrasesが保持するリストの要素(辞書)を反復処理する
        for p in self.phrases:
            # self.phrasesの'need'キーの数値と
            # パラメーターmoodをsuitable()に渡す
            # 結果がTrueであればchoicesリストに'phrase'キーの応答例を追加
            if (self.suitable(p['need'], mood)):
                choices.append(p['phrase'])
        # choicesリストが空であればNoneを返す
        if (len(choices) == 0):
            return None
            # choicesリストが空でなければランダムに
            # 応答文字列を選択して返す
        return random.choice(choices)

    def suitable(self, need, mood):
        #機嫌値
        # 必要機嫌値が0であればTrueを返す
        if (need == 0):
            return True
        # 必要機嫌値がプラスの場合は機嫌値が必要機嫌値を超えているか判定
        elif (need > 0):
            return (mood > need)
        # 応答例の数値がマイナスの場合は機嫌値が下回っているか判定
        else:
            return (mood < need)

    def add_phrase(self, phrase):
        #応答例
        # インプット文字列がリストの応答例に合うか
        # self.phrases  マッチした応答フレーズの辞書リスト
        for p in self.phrases:
            #print('phrases===',p)
            # 終了
            if p['phrase'] == phrase:
                return
        # phrasesリストに辞書を追加
        # {'need'  :0, 'phrase':インプット文字列}
        self.phrases.append({'need': 0, 'phrase': phrase})

    def make_line(self):
        """パターン辞書1行ぶんのデータを作る
        """
        # 必要機嫌値 + '##' + パターン
        pattern = str(self.modify) + '##' + self.pattern
        phrases= []
        for p in self.phrases:
            resp = str(p['need']) + '##' + str(p['phrase'])
            phrases.append(str(p['need']) + '##' + str(p['phrase']))
        line = pattern + '\t' + '|'.join(phrases)
        return pattern + '\t' + '|'.join(phrases)


こちらが辞書ファイルです。

試したこと

エラーがわからないため何も触れていません。

補足情報(FW/ツールのバージョンなど)

python3.6です  辞書プログラムのほかに、応答、AI本体のクラス、Tkinterに載せるプログラム、analyzerのプログラムがあります。
必要でしたらそちらも載せます。 

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

google翻訳
位置0で何も繰り返さない

そのエラーが出た行(あるいはその前後の行)で、使用している変数の内容をprintするなどして中になにが入ってるのか確認してみよう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る