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

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

ただいまの
回答率

88.19%

クラスがインポートできない!

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 550

Ponde_ling

score 8

概要

GUIの実行画面に入力したものに対しての返答の文字が出力されない状態で困っています。おそらくメインクラスに他のクラスをインポート出来ていないためだと考えています。今回作成したコードは、GUIの(Ray1.py)、メインクラス(ray.py)、辞書クラス(dictionary.py)と応答クラス(responder.py)であり、応答クラス(responder.py)だけがインポートできない状態で困っています。まだ初心者なので優しく教えてください(>_<)

補足

ray.pyの from responder import * が開発ツール(PyCharm)で薄く表示されるのと、 self.res_history = HistoryResponder(self.dictionary) 、
self.study_history = StudyHistoryResponder(self.dictionary) 
の部分に赤い波線(エラー?)が出ることや、実行画面で返答がないことから、インポート出来ていないと考えました。実行してもエラー表示は出ません。

コード

dictionary.py

class Dictionary:

    def __init__(self):
        """ 辞書オブジェクトの作成
        """

        self.__load_history()

    def __load_history(self):
        """ファイルを読み込み、世界史の辞書オブジェクトを作成
        """
        with open('data1/world_history.txt', 'r', encoding='utf_8'
                  ) as file:
            lines = file.readlines()

        new_lines = []

        for line in lines:
            line = line.rstrip('\n')
            if line != '':
                new_lines.append(line)
        separate = []
        for line in new_lines:
            sp = line.split('\t')
            separate.append(sp)
        self.__history = dict(separate)

    def save(self):
        """self.historyの内容を加工してファイルに書き込む
        """
        write_lines = []

        for key, val in self.history.items():
            write_lines.append(key + '\t' + val + '\n')
        with open('data1/world_history.txt', 'w', encoding='utf_8') as f:
            f.writelines(write_lines)

    def get_history(self):
        return self.__history

    def set_history(self, history):
        self.__history = history

    history = property(get_history, set_history)


if __name__ == '__main__':
    dictionary = Dictionary()
    print(dictionary.history)
    dictionary.save()

responder.py

from dictionary import *


class Responder:
    def __init__(self, dictionary):
        self.__dictionary = dictionary

    def response(self, input, what):
        return ''

    # __historyのゲッター
    def get_dictionary(self):
        return self.__dictionary

    #  __historyのセッター
    def set_dictionary(self, history):
        self.__history = history

    dictionary = property(get_dictionary, set_dictionary)


class HistoryResponder(Responder):
    def response(self, input, what):
        if input in self.dictionary.history:
            return '「' + self.dictionary.history[input] + '」です。'
        else:
            return '理解できませんでした。答えを入力して下さい。'


class StudyHistoryResponder(Responder):
    def response(self, input, what):
        self.dictionary.history[what] = input
        return '記憶しました'


if __name__ == '__main__':
    dictionary = Dictionary()
    # responder = HistoryResponder(dictionary)
    history_resp = HistoryResponder(dictionary)
    ans = history_resp.response('世界四大文明', '')
    print(ans)

    study_resp = StudyHistoryResponder(dictionary)
    ans = study_resp.response('ディアドコイ', 'アレクサンドロス大王の後継者')
    print(dictionary.history)

ray.py

from responder import *
from dictionary import *


class Ray:
    def __init__(self):

        self.__dictionary = Dictionary()

        self.__res_history = HistoryResponder(self.__dictionary)

        self.__study_history = StudyHistoryResponder(self.__dictionary)

    def dialogue(self, input, subject, study, what):
        if subject == 0 and study == 0:
            self.responder = self.res_history

        elif subject == 0 and study == 1:
            self.responder = self.study_history

        return self.responder.response(input, what)

    def save(self):
        """ Dictionaryのsave()を呼ぶ中継メソッド
        """
        self.dictionary.save()

    @property
    def dictionary(self):
        return self.__dictionary

    @property
    def res_history(self):
        return self.__res_history

    @property
    def study_history(self):
        return self.__study_history


if __name__ == '__main__':
    ray = Ray()
    ans = ray.dialogue('世界四大文明', 0, 0, '')
    print(ans)

    ans = ray.dialogue('アレクサンドロス大王の後継者', 0, 0, '')
    print(ans)

    ans = ray.dialogue('ディアドコイ', 0, 1, 'アレクサンドロス大王の継続者')
    print(ans)
    print(ray.dictionary.history)

    ray.save()

world_history.txt

古代ギリシアの植民市    ビサンティウム、ネアポリス、マッサリア
古代ギリシアの三大悲劇詩人    アイスキュロス、ソフォクレス、エウリピデス
シェイクスピアの四大悲劇    オセロ、マクベス、リア王、ハムレット
ローマ帝王の五賢帝    ネルヴァ、トラヤヌス、ハドリアヌス、アントニヌス・ピウス、マルクス・アウレリウス・アントニヌス
カースト制度の身分    バラモン、クシャトリヤ、ヴァイシャ、シュードラ
ロシアの歴代大統領    エリッツン、プーチン、メドヴェージェフ
世界四大文明    エジプト文明、メソポタミア文明、インダス文明、黄河文明
三国志の三国    魏、呉、蜀
ルネサンス期の三大発明    火薬、羅針盤、活版印刷
三国時代の三国    高句麗、百済、新羅
アレクサンドロス大王の継続者    ディアドコイ

Ray1.py

from rayl.ray import *
import tkinter
import tkinter.messagebox
import re

tk = tkinter

entry = None
response_area = None
action = None
ray = Ray()
study = 0
what = ''


def talk():
    global study, what

    value = entry.get()
    subject = action.get()
    print('Formsubject==', subject)
    print('Formstudy==', study)
    if not value:
        response_area.configure(text='ご用件をお申し付け下さい')
    elif subject == 0 and study == 0:
        response = ray.dialogue(value, subject, study, what)
        response_area.configure(text=response)
        m = re.match('理解できませんでした。', response)
        print('m===', m)
        if m:
            study = 1
            what = value
        entry.delete(0, tk.END)
    elif subject == 0 and study == 1:
        response = ray.dialogue(value, subject, study, what)
        response_area.configure(text=response)
        study = 0
        what = ''
        entry.delete(0, tk.END)


def run():
    global entry, response_area, action


root = tk.Tk()
root.title("Super Bot --Ray1-- : ")
# ウィンドウサイズ
root.geometry("880x460")
# フォント
font = ('Helevetica', 14)


def calloback():
    if tkinter.messagebox.askyesno('Quit?', '辞書を更新してもよろしいですか'):
        ray.save()
        root.destroy()
    else:
        root.destroy()


root.protocol('WM_DELETE_WINDOW', calloback)

# メニューバーの作成
menubar = tk.Menu(root)
filemenu = tk.Menu(menubar, tearoff=0)

# ファイルメニュー
filemenu.add_command(label="閉じる", command=calloback)
menubar.add_cascade(label="ファイル", menu=filemenu)

# 編集メニュー
optionmenue = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="科目", menu=optionmenue)
optionmenue.add_radiobutton(label='世界史', variable=action, value=0)
optionmenue.add_radiobutton(label='英語(単語)', variable=action, value=1)
root.config(menu=menubar)

# 上の画像
# 画像サイズ(横x縦)
c = tk.Canvas(root, width=870, height=200, relief=tk.RIDGE, bd=2)
c.pack()
c.place(x=1, y=0)
nw = tk.PhotoImage(file='img1.gif')
# 画像の位置
c.create_image(0, 0, anchor=tk.NW)

# 背景
response_area = tk.Label(root, width=86, height=10, bg='White', font=font, relief=tk.RIDGE, bd=2)
response_area.place(x=6, y=210)

# フレームの作成
frame = tk.Frame(root, bd=4, relief=tk.RIDGE)

# 入力ボックスの作成
entry = tk.Entry(frame, width=70, font=font)
entry.pack(side=tk.LEFT)
entry.focus_set()

button = tk.Button(frame, width=15, text='入力')
button.pack(side=tk.LEFT)

frame.place(x=30, y=420)

root.mainloop()

if __name__ == '__main__':
    run()

dictionaly.py実行結果

{'古代ギリシアの植民市': 'ビサンティウム、ネアポリス、マッサリア', '古代ギリシアの三大悲劇詩人': 'アイスキュロス、ソフォクレス、エウリピデス', 'シェイクスピアの四大悲劇': 'オセロ、マクベス、リア王、ハムレット', 'ローマ帝王の五賢帝': 'ネルヴァ、トラヤヌス、ハドリアヌス、アントニヌス・ピウス、マルクス・アウレリウス・アントニヌス', 'カースト制度の身分': 'バラモン、クシャトリヤ、ヴァイシャ、シュードラ', 'ロシアの歴代大統領': 'エリッツン、プーチン、メドヴェージェフ', '世界四大文明': 'エジプト文明、メソポタミア文明、インダス文明、黄河文明', '三国志の三国': '魏、呉、蜀', 'ルネサンス期の三大発明': '火薬、羅針盤、活版印刷', '三国時代の三国': '高句麗、百済、新羅', 'アレクサンドロス大王の継続者': 'ディアドコイ'}

Process finished with exit code 0

responder.py実行結果

「エジプト文明、メソポタミア文明、インダス文明、黄河文明」です。
{'古代ギリシアの植民市': 'ビサンティウム、ネアポリス、マッサリア', '古代ギリシアの三大悲劇詩人': 'アイスキュロス、ソフォクレス、エウリピデス', 'シェイクスピアの四大悲劇': 'オセロ、マクベス、リア王、ハムレット', 'ローマ帝王の五賢帝': 'ネルヴァ、トラヤヌス、ハドリアヌス、アントニヌス・ピウス、マルクス・アウレリウス・アントニヌス', 'カースト制度の身分': 'バラモン、クシャトリヤ、ヴァイシャ、シュードラ', 'ロシアの歴代大統領': 'エリッツン、プーチン、メドヴェージェフ', '世界四大文明': 'エジプト文明、メソポタミア文明、インダス文明、黄河文明', '三国志の三国': '魏、呉、蜀', 'ルネサンス期の三大発明': '火薬、羅針盤、活版印刷', '三国時代の三国': '高句麗、百済、新羅', 'アレクサンドロス大王の継続者': 'ディアドコイ', 'アレクサンドロス大王の後継者': 'ディアドコイ'}

Process finished with exit code 0

ray.py実行結果

理解できませんでした。答えを入力して下さい。
記憶しました
{'古代ギリシアの植民市': 'ビサンティウム、ネアポリス、マッサリア', '古代ギリシアの三大悲劇詩人': 'アイスキュロス、ソフォクレス、エウリピデス', 'シェイクスピアの四大悲劇': 'オセロ、マクベス、リア王、ハムレット', 'ローマ帝王の五賢帝': 'ネルヴァ、トラヤヌス、ハドリアヌス、アントニヌス・ピウス、マルクス・アウレリウス・アントニヌス', 'カースト制度の身分': 'バラモン、クシャトリヤ、ヴァイシャ、シュードラ', 'ロシアの歴代大統領': 'エリッツン、プーチン、メドヴェージェフ', '世界四大文明': 'エジプト文明、メソポタミア文明、インダス文明、黄河文明', '三国志の三国': '魏、呉、蜀', 'ルネサンス期の三大発明': '火薬、羅針盤、活版印刷', '三国時代の三国': '高句麗、百済、新羅', 'アレクサンドロス大王の継続者': 'ディアドコイ'}

Process finished with exit code 0

コード

各コード、画像、テキストの保存場所
各コード、画像、テキストの保存場所
イメージ説明
イメージ説明

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

importに失敗している、というのは質問文の状況から行った推測であって、実行した際にエラーなどが出るわけではないのですね?

pythonではimportの失敗はエラー(例外)になりますから、エラーが出なければ何らかの形でimportには成功しています。原因は他の部分にあるのだと思います。


GUIのRay1.pyのコードに定義されているtalk関数についてですが、このプログラムの中核になる処理のように見えるのに、コード内で呼び出される仕組みがないようです。意図通り動作しないのはそのせいではないでしょうか。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/10/26 10:18

    ご回答ありがとうございます。コードの方確認してみます

    キャンセル

  • 2019/10/27 19:12

    コードをすべて理解した訳ではありませんが、雰囲気からするとたぶんtalkは
    button = tk.Button(frame, width=15, text='入力')
    のcommandとかに指定すべきものなのでしょう。
    単にそれだけでちゃんと動くという訳でもなさそうなので、しっかり確認していただくのがいいと思いますが、とりあえずそれで。

    キャンセル

  • 2019/10/28 07:04

    ありがとうございます。試してみます。

    キャンセル

  • 2019/10/28 17:08

    出力した際の表示の画像を添付しました。ウィンドの上部に画像img1.gifが出力されていないのと、入力エリアに未入力の場合「ご用件をお申し付け下さい」と出力してほしいのですが出力されていません。

    キャンセル

0

知識がなく、適当な回答になるので、こちらで…

Pythonには学が無いので、あくまで記載されてる情報から、
「もしかしたら」程度で答えます…あまり期待しないでください…

>辞書クラス(dictionary.py)と応答クラス(responder.py)であり、応答クラス(responder.py)だけがインポートできない状態

この発言が事実であれば、「辞書クラス」と「応答クラス」の違いから見てみました。

●辞書クラス

class Dictionary

しかない

●応答クラス

class Responder:

の他にも

class HistoryResponder(Responder):
class StudyHistoryResponder(Responder):

がある。

>from responder import * が開発ツール(PyCharm)で薄く表示

>self.res_history = HistoryResponder(self.dictionary) 、
>self.study_history = StudyHistoryResponder(self.dictionary) 
>の部分に赤い波線(エラー?)が出ることや

から、ray.pyが

「responder import *」がなんて使ってねーよ! と言ってる のと
「HistoryResponder」と「StudyHistoryResponder」が見つからねーよ!と言ってるように見受けられます…

●想定される解決策

responder import * を

from responder import HistoryResponder
from responder import StudyHistoryResponder

のような、

「responder」に宣言されたクラスを個別に読み込む

ようなinport宣言というのは出来ないものなのでしょうか…。

(上記記述だと間違いなくエラーがでると思いますが、「responder 」に対しての「HistoryResponder
」や「StudyHistoryResponder」のimport指定のやり方はあると思われます…)

少なくともC#でusingといった似たような宣言があるのですが、
質問主の事象だと「*なんて曖昧な表現せずにちゃんと細かく指定しろ」みたいな怒られ方をすることがあるので
似たような次第だと思いました…

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/10/25 11:45

    丁寧なご回答ありがとうございます。検討させて頂きます。

    キャンセル

  • 2019/10/27 19:05

    >hermit19901127さん
    from responder import HistoryResponder
    from responder import StudyHistoryResponder
    はまさにその通りの記述で良いので、「上記記述だと間違いなくエラーがでると思いますが」は間違いですね。修正されてはいかがでしょうか。
    *を使ったimportはPEP8などでも推奨されていません(https://pep8-ja.readthedocs.io/ja/latest/#import)。多くのlintはそれ自体に警告を出しますし、静的解析ではこれによってimportされる名前は存在しないとして扱われるのが普通だと思います。
    ただし、実行時にちゃんと名前解決できれば(実行ができるかどうかという観点だけで見れば)問題はありません。その場合は、
    from responder import *

    from responder import HistoryResponder
    from responder import StudyHistoryResponder
    に大きな違いはありません。
    (つまりresponderモジュール配下にHistoryResponderとStudyHistoryResponderが実際に存在していればワイルドカード・インポートでもうまくいく。他の名前で名前空間が汚れる副作用はありますが)

    キャンセル

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

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

関連した質問

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