Por que trocar sinais causa NameErrors em um código sane? - questão PyGtk

2

Estou trabalhando em um aplicativo muito simples para o Ubuntu. Fiz uma pergunta em stackoverflow , e parece que a questão que estou tendo é causada por sinais, não pelo escopo de variáveis, como eu pensava inicialmente. O problema que estou tendo é que quando TextBox emite um sinal através de activate todo o código funciona sem uma falha. Mas quando eu mudo o sinal para insert-at-click , ele retorna NameErrors em cada função não- TextBox -linked. Agora, é altamente possível que eu esteja fazendo algo completamente errado aqui, mas é pelo menos provável que os sinais possam afetar as atribuições de variáveis globais?

O código em sua forma atual me dando 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)
    
por boywithaxe 24.06.2012 / 02:01

1 resposta

2

Você está entendendo mal o significado da instrução global no Python. Veja o que a documentação do Python diz:

The global statement ... means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global, although free variables may refer to globals without being declared global.

Então, basicamente, você só precisa usar global blah quando precisar atribuir a uma variável global chamada blah . A variável, no entanto, já deveria existir no escopo global. Se você está apenas acessando uma variável global ou seus métodos (como determinado a atribuir a ela), não é necessário declará-la como global .

Então, o que você precisa é algo como

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')

...

No entanto, toda a abordagem com o uso de uma variável global e tornando a coisa toda dependente da ordem das chamadas de função (on_servername_insertatcursor DEVE ser chamada primeiro, caso contrário, as outras funções falharão) não é uma boa prática de codificação.

UPDATE: Além disso, ocorreu-me que as funções que você está mostrando são de fato métodos de uma classe, certo? Nesse caso, você pode tornar output um membro da classe e acessá-lo como 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')

Ainda assim, a saída do seu aplicativo depende do usuário do pedido clicar nos botões, o que não é legal. Por exemplo, se o usuário clicar na caixa de seleção "dlna" duas vezes, haverá duas linhas na configuração, o que presumo que não seja o que você deseja.

    
por Sergey 25.06.2012 / 00:03