代码没有传递"检查"变量起作用

时间:2012-05-24 17:19:55

标签: python tk

我正在尝试将名为checks的变量列表传递给函数installFunc,由于某种原因它似乎不起作用,这就是我(想到的)相关代码:

def installFunc(checks):
    subprocess.call("md c:\MGInstall", shell=True)
    subprocess.call (u"net use w: \\it01\files")
    if checks[0] == 1:
        subprocess.call(u"w:\\software\\snagitup.exe")
    if checks[1] == 1:
        subprocess.call(u"w:\\software\\camtasia.exe")
    if checks[2] == 1:
        urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\gotomeeting.exe")
        subprocess.call (u"c:\\MGinstall\\gotomeeting.exe")
    if checks[3] == 1:
        sixtyfourcheck()
        if is64bit == True:
            urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\tortoiseSVN.exe")
        elif is64bit == False:
            urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\tortoiseSVN.exe")
    #urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\MGinstall.exe")
    #subprocess.call (u"c:\\MGinstall\\MGinstall.exe")
    #subprocess.call (u"w:\\printers\\installer\\printer.exe")

app = Tk()

w = Label(app, text="IT Automatic Installer")
w.pack()

text = ["Snagit", "Camtasia", "GotoMeeting", "TortoiseSVN"]
variables = []
for name in text:
    variables.append(IntVar())
    Checkbutton(text=name, variable=variables[-1]).pack()

checks = [variable.get() for variable in variables]
b = Button(text="Install", command= lambda : installFunc(checks))
b.pack()

app.mainloop()

现在,我尝试了一些不同的东西 - 我实际上是通过堆栈溢出给出的lamba部分 - 我在理解其工作原理时遇到了一些麻烦。

但我遇到的一个大问题是 - 为什么检查不会传递给installFunc()?我希望将完整的检查列表(尽可能多的项目)传递给installFunc()。

3 个答案:

答案 0 :(得分:2)

variable.get()会在应用程序启动之前返回IntVar实例的值。所以,它将充满零。

def installCommand(variables):
    checks = [variable.get() for variable in variables]
    return installFunc(checks)

b = Button(text="Install", command= lambda v=variables: installCommand(v))
b.pack()

此外,您需要将variables作为默认参数传递给lambda,这样就不会与全局和局部变量发生冲突。

答案 1 :(得分:0)

至少你可以通过几种方式做到这一点。就个人而言,我会将安装程序抽象为一个对象,正如Hugh Bothwell的评论所述。这具有最大的灵活性和简洁的国家遏制。但是,如果您只使用一个函数,则可以使用functools“curry”函数:动态创建一个嵌入给定参数的新函数。以下是您需要做的更改......

def installFunc(checks):
    subprocess.call("md c:\MGInstall", shell=True)
    subprocess.call (u"net use w: \\it01\files")
    if checks[0].get( ) == 1:
        subprocess.call(u"w:\\software\\snagitup.exe")
    if checks[1].get( ) == 1:
        subprocess.call(u"w:\\software\\camtasia.exe")
    if checks[2].get( ) == 1:
        urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\gotomeeting.exe")
        subprocess.call (u"c:\\MGinstall\\gotomeeting.exe")
    if checks[3].get( ) == 1:
        sixtyfourcheck()
        if is64bit == True:
            urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\tortoiseSVN.exe")
        elif is64bit == False:
            urllib.urlretrieve(u"LONGURL", u"c:\\MGinstall\\tortoiseSVN.exe")


import functools

app = Tk()

w = Label(app, text="IT Automatic Installer")
w.pack()

text = ["Snagit", "Camtasia", "GotoMeeting", "TortoiseSVN"]
variables = []
for name in text:
    variables.append(IntVar())
    Checkbutton(text=name, variable=variables[-1]).pack()

checks = [variable.get() for variable in variables]

#-- Here's where we "curry" the installFunc, producing the new doInstall function.
doInstall = functools.partial(installFunc, checks)

b = Button(text="Install", command = doInstall)
b.pack()

app.mainloop()

这里的问题是variable.get()创建了一个不可变的int,你的列表“checks”永远不会改变。你真正想要的是......

import functools

app = Tk()

w = Label(app, text="IT Automatic Installer")
w.pack()

text = ["Snagit", "Camtasia", "GotoMeeting", "TortoiseSVN"]
variables = []
for name in text:
    variables.append(IntVar())
    Checkbutton(text=name, variable=variables[-1]).pack()

checks = [variable for variable in variables]

#-- Here's where we "curry" the installFunc, producing the new doInstall function.
doInstall = functools.partial(installFunc, checks)

b = Button(text="Install", command = doInstall)
b.pack()

app.mainloop()

答案 2 :(得分:0)

根据我之前的评论,重构版本:

import urllib
import subprocess
import os
import Tkinter as tk

class ProgramInstaller(object):
    def __init__(self, name, descr, do_install):
        self.name    = name
        self.descr   = descr
        self.do_install = do_install    # can be function or list of strings

    def install(self):
        if callable(self.do_install):
            self.do_install()
        else:
            for s in self.do_install:
                subprocess.call(s)

TEMP_DIR = r"c:\MGInstall"

def makeTempDir(dir=TEMP_DIR):
    # need to expand on this - what if dir already exists, etc
    os.mkdir(dir)

def removeTempDir(dir=TEMP_DIR):
    # need to expand on this - del files in dir before rmdir, etc
    os.rmdir(dir)

def installGoToMeeting():
    makeTempDir()
    url = "http://www.gotomeeting.com/download/something"
    fname = os.path.join(TEMP_DIR, "gotomeeting.exe")
    urllib.urlretrieve(url, fname)
    subprocess.call(fname)
    removeTempDir()

def installTortoiseSVN():
    makeTempDir()
    if is64bit(): url = "http://www.tortoisesvn.net/download/something/64bit"
    else:         url = "http://www.tortoisesvn.net/download/something/32bit"
    fname = os.join(TEMP_DIR, "tortoisesvn.exe")
    urllib.urlretrieve(url, fname)
    subprocess.call(fname)
    removeTempDir()

installers = (
    ProgramInstaller("SnagIt",      "Take screen-shots",           [r"net use w: \\it01\files", r"w:\software\snagitup.exe"]),
    ProgramInstaller("Camtasia",    "Record your desktop",         [r"net use w: \\it01\files", r"w:\software\camtasia.exe"]),
    ProgramInstaller("GoToMeeting", "Web conferencing",            installGoToMeeting),
    ProgramInstaller("TortoiseSVN", "(Sub)Version control client", installTortoiseSVN),
    ProgramInstaller("Printer",     "HP4020 Printer drivers",      [r"net use w: \\it01\files", r"w:\printers\installer\printer.exe"])
)

def doInstall():        # install-button callback
    for inst in installers:
        if inst.cbvar.get():
            inst.install()

def main():
    app = tk.Tk()
    tk.Label(app, text="IT Automatic Installer").pack()

    # need to fiddle with a grid layout to make this look right
    for inst in installers:
        inst.cbvar = tk.IntVar()
        tk.Checkbutton(text=inst.name, variable=inst.cbvar).pack()
        tk.Label(text=inst.descr).pack()

    tk.Button(text="Install", command=doInstall()).pack()
    app.mainloop()

if __name__=="__main__":
    main()