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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Q&A

解決済

1回答

5121閲覧

pythonのTkinterでクライアントGUIを作ったのですが、エラーが出てしまいます。

0chihiro0

総合スコア7

Python 3.x

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

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

0グッド

0クリップ

投稿2016/11/12 05:44

編集2016/11/12 19:11

###前提・実現したいこと
参考書を読みながら、Echoアプリケーションを作成中です。
言語はPythonで、Tkinter,syncore,functoolsライブラリを使っています。
今回のコードはクライアント側なのですが、実行しようとしてもエラーが出てしまい、GUIの画面もうまく表示されません。
こういう場で質問することが初めてなので、至らないところがあるかもしれないので、その時はご指摘ください。

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

Traceback (most recent call last): File "/Users/CHIHIRO/Downloads/Python/Part3/11/client.py", line 76, in <module> main() File "/Users/CHIHIRO/Downloads/Python/Part3/11/client.py", line 68, in main root.after(200, functools.partial(idle_task, root)) File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/tkinter/__init__.py", line 593, in after callit.__name__ = func.__name__ AttributeError: 'functools.partial' object has no attribute '__name__'

###該当のソースコード

Python3

1# -*- coding::utf-8 -*- 2 3import tkinter 4import asyncore 5import functools 6 7class EchoView(tkinter.Frame): 8 """ Echo User Interface """ 9 10 def __init__(self, master): 11 super(EchoView, self).__init__(master) 12 self.listcontainer = tkinter.Frame(self) 13 self.listbox = tkinter.Listbox(self.listcontainer) 14 self.yscroll = tkinter.Scrollbar(self.listcontainer) 15 self.listbox.pack(side=tkinter.LEFT, expand=True, fill=tkinter.BOTH) 16 self.yscroll.pack(side=tkinter.LEFT, expand=True, fill=tkinter.Y) 17 self.listcontainer.pack(expand=True, fill=tkinter.BOTH) 18 19 self.entry = tkinter.Entry(self) 20 self.entry.pack(side=tkinter.BOTTOM, expand=True, fill=tkinter.X) 21 22 def get_submit_messegae(self): 23 data = self.entry.get() 24 self.entry.delete(0, tkinter.END) 25 return data 26 27 def show_message(self, message): 28 self.listbox.insert(tkinter.END, message) 29 self.listbox.see(tkinter.END) 30 31class EchoClient(asyncore.dispatcher_with_send): 32 def __init__(self, view): 33 super(EchoClient, self).__init__() 34 self.create_socket() 35 self.buffers = [] 36 self.view = view 37 self.bind_all() 38 39 def bind_all(self): 40 self.view.entry.bind('<Return>', self.on_submit) 41 42 def on_submit(self, event): 43 message = self.view.get_submit_messegae() 44 self.buffers.append(message.encode('utf-8')) 45 46 def handle_write(self): 47 if not self.buffers: 48 return 49 buffer, self.buffers = self.buffers[0],self.buffers[1:] 50 self.send(buffer) 51 52 def writable(self): 53 return self.buffers 54 55 56 def handle_read(self): 57 message = self.recv(8192) 58 self.view.show_message(message.decode('utf-8')) 59 60def idle_task(root): 61 try: 62 asyncore.loop(count=1, timeout=1) 63 finally: 64 root.after(200, functools.partial(idle_task, root)) 65 66def main(): 67 root = tkinter.Tk() 68 root.after(200, functools.partial(idle_task, root)) 69 view = EchoView(root) 70 view.pack(expand=True, fill=tkinter.BOTH) 71 client = EchoClient(view) 72 client.connect(('localhost', 8080)) 73 root.mainloop() 74 75if __name__ == '__main__': 76 main() 77 78 79

###試したこと
エラーメッセージにmain関数のfunctools.partailの部分が出ているので、functorsのドキュメントを読んだのですが、自分では原因がわかりませんでした。
ですので、助けて頂けるとありがたいです。
よろしくお願いします。

###補足情報(言語/FW/ツール等のバージョンなど)
Python3.4.4

『パーフェクトPython』:
著 Pythonサポーターズ:
発行 技術評論社:
11章チャットアプリケーションのP230~P235の部分です

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

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

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

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

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

ikedas

2016/11/12 06:44

Pythonのバージョンを明記してください。また、参考にしている書籍 (著者・標題・出版社と、参考にした箇所のページ数) も教えてもらえますか。
0chihiro0

2016/11/12 21:09

ご指摘ありがとうございます。編集しておきました。次からは載せるようにします。
guest

回答1

0

ベストアンサー

tinter,syncope,functorsライブラリを使っています。

見事に全部に typo が・・・閑話休題

エラーの原因ですが tkinter の内部の変更によるものの様です。

詳細なバージョンは解りませんが、おそらく 3.4.x の途中からの変更で、
3.4.0 ではエラーは出ませんでした。

修正方法

エラーログより、functools.partial で生成したオブジェクトには __name__ 属性がないようなので、
通常のように関数を定義して渡す、もしくは lambda 式 でコールバックを渡すことで回避します。

functools.partail(idle_task, root)

となっている2箇所を

lambda:idle_task(root)

と変更し試してみて下さい。
エラー無しでウィンドウが出るところまでは確認しました。@ win10 / 3.5.0, 3.6.0a2

投稿2016/11/12 07:58

編集2016/11/12 08:01
teamikl

総合スコア8664

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

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

0chihiro0

2016/11/12 21:06

GUIが無事に表示されました。 lambdaについてももっと勉強します。 ありがとうございました。
teamikl

2016/11/13 15:35

すいません。説明不足だったので少し補足させてください。 lambda の利用は、このコードでの 一時的な回避策の為 でした。 実際の Python のプログラムでは、コールバックを引数に渡すようなところでは、 partial の利用が推奨されてます。例えば、asyncio というモジュールのコールバックの説明では http://docs.python.jp/3.5/library/asyncio-eventloop.html#calls > 注釈 lambda 関数よりも functools.partial() を使用しましょう。 asyncio はデバッグモードで引数を表示するよう functools.partial() オブジェクトを精査することが出来ますが、lambda 関数の表現は貧弱です。 他の局面でも、lambda を使うところでは、 極力lambdaを使わないで代替手段を取るのが推奨されてます。 今回のコードでは、idle_task を main関数内 root を生成した後に定義すれば rootを引数に渡すために functools.partial や lambda を使うことなく記述できます。 ‘‘‘python def main(): root = tkinter.Tk() def idle_task(): try: asyncore.loop(count=1, timeout=1) finally: root.after(200, idle_task) root.after(200, idle_task) ‘‘‘
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問