在Python中使用全局变量

-2 投票
3 回答
1318 浏览
提问于 2025-04-17 09:23

我正在使用Tkinter来帮助我构建一个FTP客户端。在这个客户端中,我想从一个tk列表框中获取选中的信息。所以我有一个按钮来开始下载,但不管是什么原因,它总是弹出一个错误。

Exception in Tkinter callback
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__
    return self.func(*args)
  File "/Volumes/LEGO FLASH/ftp.py", line 23, in Download
    filename = stuff
NameError: global name 'stuff' is not defined" 

下面是我写的代码,供你查看:

# Import the FTP object from ftplib
from ftplib import FTP
from Tkinter import *
import os

app = Tk()
app.title("FTP")
app.geometry("300x300")

lines = []
#[lines.replace(",", "\n")for lines in lines]
#lines = lines.replace(',','\n')

def handleDownload(block):
    file.write(block)
    print ".",

def append_line(line):
    lines.append(line)

#This is where I am caught-------> 
def Download():

    filename = stuff

    file = open(filename, 'wb')

    ftp.retrbinary('RETR ' + filename, handleDownload)


    ftp.close()

def login():
    try:
        ftp.login(username.get(),password.get())
    except:
        error = Label(app, text = "Invalid USERNAME OR PASSWORD")


    label2 = Label(app, text = "Welcome to Steam Engine").pack()
    username.forget()
    password.forget()
    button.forget()

    app.geometry("800x500")

    download = Button(app, text = "Download!!!!!", command = Download)
    download.pack(side = "left", pady = "5")

    scrollBar.pack(fill = Y, side = "right", padx = "2")

    #ftp.cwd('The_Store')

    stuff = Listbox(app, height = "700", width = "500")
    ftp.retrlines('NLST', append_line)
    for i in lines:
        stuff.insert(END, i)
    stuff.pack(padx = "10", pady = "10")

    stuff.config(yscrollcommand = scrollBar.set)
    scrollBar.config(command = stuff.yview)



ftp = FTP('sciphigames.com')
label = Label(app, text = "Login").pack(pady = "10")

scrollBar = Scrollbar(app)

username = StringVar(None)
username = Entry(app, text = "Username: ")
username.pack(pady = "2")

password = StringVar(None)
password = Entry(app, text = "Password: ")
password.pack(pady = "2")

button = Button(app, text = "Login!", command = login)
button.pack(pady = "10")

app.mainloop()

任何帮助都会很感激!

谢谢!

3 个回答

0

你只需要在变量前面加上“global”这个词就可以了。

global var1
1
#This is where I am caught-------> 
def Download():

    filename = stuff

这里的 stuff 是什么呢?它不是一个全局变量,看起来像是 login 方法的一个参数,但并不是 Download 方法的参数。

如果你想把 stuff 变成一个全局变量(虽然这可能不是最好的选择),可以使用 global 语句

# Import the FTP object from ftplib
from ftplib import FTP
from Tkinter import *
import os

# define the global stuff
global stuff

...
def Download():

    global stuff

    filename = stuff

...

处理这个问题的更好方法是把这些内容放在一个对象里。

class NetworkApp(object):
   def login(self):
      # here put all the previous code of login

      # here we change the callback to self.Download
      download = Button(app, text = "Download!!!!!", command = self.Download)

      # here we're creating a stuff member
      self.stuff = Listbox(app, height = "700", width = "500")


    def Download(self):
        filename = self.stuff  # here we use the stuff member
        file = open(filename, 'wb')
        ftp.retrbinary('RETR ' + filename, handleDownload)
        ftp.close()
#...
net_app = NetworkApp()
button = Button(app, text = "Login!", command = net_app.login)
0

我不太确定你这个 stuff 变量的具体用途,但你遇到的问题可能和你使用它的方式有关。

首先,你把它当作参数传给了 login 函数(顺便说一下,这个函数其实不应该接收任何参数)。你在 login 函数里给这个变量赋值,而在你的 Download 函数里又用到了同名的另一个变量。

再次强调,我不太明白你想用 stuff 变量做什么,但我建议你可以试试下面这样的写法:

.....

app.geometry("300x300")

stuff = None # <<<<----

lines = []

.....

#This is where I am caught-------> 
def Download():
    global stuff # <<<<----

    filename = stuff

    ......

    ftp.close()

def login():
    global stuff # <<<<----

    ......

    stuff = Listbox(app, height = "700", width = "500")
    ftp.retrlines('NLST', append_line)
    for i in lines:
        stuff.insert(END, i)
    stuff.pack(padx = "10", pady = "10")

    stuff.config(yscrollcommand = scrollBar.set)
    scrollBar.config(command = stuff.yview)


......

撰写回答