web-dev-qa-db-ja.com

シグナルを変更すると、正常なコードでNameErrorsが発生するのはなぜですか? -PyGtkの問題

私はUbuntu用の非常にシンプルなアプリに取り組んでいます。 stackoverflow について質問しましたが、私が抱えている問題は、当初考えていたように、変数のスコープではなく、シグナルが原因であるようです。私が抱えている問題は、TextBoxactivateを介して信号を送信すると、コード全体がグリッチなしで機能することです。しかし、シグナルをinsert-at-clickに変更すると、TextBoxにリンクされていないすべての関数でNameErrorsが返されます。さて、ここで完全に間違ったことをしている可能性は高いですが、少なくともシグナルがグローバル変数の割り当てに影響を与える可能性はありますか?

NameErrorsを与える現在の形式のコード:

def on_servername_insertatcursor(self, widget):
global output  
output = StringIO.StringIO()         
servername = widget.get_text()
output.write("USHARE_NAME="+servername+'\n')

def on_netif_changed(self, widget):
netif = widget.get_active_text()
global output
output.write("USHARE_IFACE="+netif+'\n')

def on_port_insertatcursor(self, widget):
global output
port = widget.get_text()
output.write("USHARE_PORT="+port+'\n')

def on_telprt_insertatcursor(self, widget):
global output
telprt = widget.get_text()
output.write("USHARE_TELNET_PORT="+telprt+'\n')

def on_dirs_insertatcursor(self, widget):
global output
dirs = widget.get_text()
output.write("USHARE_DIR="+dirs+'\n')

def on_iconv_toggled(self, widget):
global output
iconv = widget.get_active()
if iconv == True:
    output.write("USHARE_OVERRIDE_ICONV_ERR="+"True"+'\n')
else:
    output.write("USHARE_OVERRIDE_ICONV_ERR="+"False"+'\n')

def on_webif_toggled(self, widget):
global output
webif = widget.get_active()
if webif == True:
    output.write("USHARE_ENABLE_WEB="+"yes"+'\n')
else:
    output.write("USHARE_ENABLE_WEB="+"no"+'\n')

def on_telif_toggled(self, widget):
global output
telif = widget.get_active()
if telif == True:
    output.write("USHARE_ENABLE_TELNET="+"yes"+'\n')
else:
    output.write("USHARE_ENABLE_TELNET="+"no"+'\n')

def on_xbox_toggled(self, widget):
global output
xbox = widget.get_active()
if xbox == True:
    output.write("USHARE_ENABLE_XBOX="+"yes"+'\n')
else:
    output.write("USHARE_ENABLE_XBOX="+"no"+'\n')

def on_dlna_toggled(self, widget):
global output
dlna = widget.get_active()
if dlna == True:
    output.write("USHARE_ENABLE_DLNA="+"yes"+'\n')
else:
    output.write("USHARE_ENABLE_DLNA="+"no"+'\n')

def on_commit_clicked(self, widget):
commit = output.getvalue()
logfile = open('/home/boywithaxe/Desktop/ushare.conf','w')
logfile.write(commit)

def on_endprogram_clicked(self, widget):
sys.exit(0)
2
boywithaxe

Pythonでのglobalステートメントの意味を誤解しています。 Pythonドキュメントの内容は次のとおりです。

グローバルステートメント...は、リストされた識別子がグローバルとして解釈されることを意味します。自由変数はグローバルとして宣言されずにグローバルを参照する場合がありますが、グローバルなしでグローバル変数に割り当てることは不可能です。

したがって、基本的には、blahというグローバル変数に割り当てる必要がある場合にのみglobal blahを使用する必要があります。ただし、変数はすでにグローバルスコープに存在している必要があります。グローバル変数またはそのメソッドにアクセスしているだけの場合(割り当てに応じて)、globalとして宣言する必要はありません。

だからあなたが必要なのは

output = None

def on_servername_insertatcursor(self, widget):
    global output  
    output = StringIO.StringIO()         
    servername = widget.get_text()
    output.write("USHARE_NAME="+servername+'\n')

def on_netif_changed(self, widget):
    netif = widget.get_active_text()
    output.write("USHARE_IFACE="+netif+'\n')

...

ただし、グローバル変数を使用し、関数呼び出しの順序にすべてを依存させるというアプローチ全体(on_servername_insertatcursorを最初に呼び出す必要があります。そうしないと、他の関数が失敗します)は適切なコーディング方法ではありません。

PDATE:また、あなたが示している関数は実際にはクラスのメソッドであることに気づきましたね。この場合、outputをクラスのメンバーにして、self.outputとしてアクセスできます。

class MyApp(gtk.Window):

    output = None

    def __init__(...):
        ...
        self.output = StringIO.StringIO()

    def on_servername_insertatcursor(self, widget):    
        servername = widget.get_text()
        self.output.write("USHARE_NAME="+servername+'\n')

    def on_netif_changed(self, widget):
        netif = widget.get_active_text()
        self.output.write("USHARE_IFACE="+netif+'\n')

それでも、アプリの出力は、ユーザーがボタンをクリックする順序に依存しますが、これはクールではありません。たとえば、ユーザーが「dlna」チェックボックスを2回クリックすると、構成に2行が表示されますが、これは希望どおりではないと思います。

2
Sergey