2017-03-17 7 views
0

Ich habe eine Tkinter GUI mit drei Tasten, die jeweils ein separates Skript ausführen. Zwei von ihnen laden gut, aber die dritte wirft einen NameError, sagen, einer meiner Namen ist nicht definiert. Wenn ich das Skript jedoch nicht über die GUI ausführe, läuft es einwandfrei.Tkinter Button Ausführen des Skripts wirft NameError

Dies ist die GUI-Code:

import sys 
import os 
import tkinter 
import cv2 
from tkinter.filedialog import askopenfilename 
from tkinter import messagebox 
import numpy as np 
import matplotlib.pyplot as plt 

top=tkinter.Tk() 
top.geometry("300x350") 
top.config(background='black') 
top.title('Test') 
top.resizable(height=False, width=False) 

def thresholdCallBack(): 
    exec(open('motionindexthreshold.py').read()) 

def autoremoveCallBack(): 
    exec(open('motionindexgenerator.py').read()) 

def videoTaggingCallBack(): 
    exec(open('stepthrough.py').read()) 

def quitCallBack(): 
    top.destroy() 

M = tkinter.Message(top, text='Test', width=280, background='black', foreground='white', font=('Courier', 28)) 
B = tkinter.Button(top,text="Define Motion Index Threshold",command= thresholdCallBack) 
C = tkinter.Button(top,text="Autoremove Nonmovement Video Segments",command= autoremoveCallBack) 
D = tkinter.Button(top,text="Tag Video Frames",command= videoTaggingCallBack) 
E = tkinter.Button(top,text="Quit", command=quitCallBack) 
B.config(height=5, width=80, background='red') 
C.config(height=5, width=80, background='blue', foreground='white') 
D.config(height=5, width=80, background='yellow') 
E.config(height=5, width=80, background='green') 
M.pack() 
B.pack() 
C.pack() 
D.pack() 
E.pack() 
top.mainloop() 

Und das ist das Python-Skript, das stürzt ab, wenn ein Tastendruck registriert ist:

import cv2 
import tkinter as tk 
from tkinter.filedialog import askopenfilename 
from tkinter import messagebox 
import numpy as np 
import os 
import matplotlib.pyplot as plt 
import sys 


framevalues = [] 
count = 1 

root = tk.Tk() 
root.withdraw() 

selectedvideo = askopenfilename() 
selectedvideostring = str(selectedvideo) 
cap = cv2.VideoCapture(selectedvideo) 
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 


def stanceTag():  
    framevalues.append('0' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def swingTag(): 
    framevalues.append('1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def unsureTag(): 
    framevalues.append('-1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def rewindFrames(): 
    cap.set(1,((int(cap.get(1)) - 2))) 
    print (int(cap.get(1)), '/', length) 
    framevalues.pop() 
    print(framevalues) 



while (cap.isOpened()): 
    ret, frame = cap.read() 

    # check if read frame was successful 
    if ret == False: 
      break 
    # show frame first 
    cv2.imshow('frame',frame) 

    # then waitKey 
    frameclick = cv2.waitKey(0) & 0xFF 

    if frameclick == ord('a'): 
     swingTag() 

    elif frameclick == ord('r'): 
     rewindFrames() 

    elif frameclick == ord('s'): 
     stanceTag() 

    elif frameclick == ord('d'): 
     unsureTag() 

    elif frameclick == ord('q'): 
     with open((selectedvideostring + '.txt'), 'w') as textfile: 
      for item in framevalues: 
       textfile.write("{}\n".format(item)) 
     break 

    else: 
     continue 

cap.release() 
cv2.destroyAllWindows() 

Hat jemand irgendwelche Ideen haben, wie dieses Problem zu lösen?

Dank

+0

Etwas wird von Ihrem GUI-Skript importiert und nicht durch den Index. Der NameError wird Ihnen sagen, welcher Name fehlt. Die Lösung wäre, einen korrekten Import zu verwenden, um die Skripte auszuführen anstatt exec. – Novel

Antwort

2

Wenn Sie Code aus einem anderen Python-Skript ausführen müssen, dann sollten Sie einen Import verwenden, um die anderen Skript zu erhalten und eine Funktion in dem anderen Skript ausführen. Das wird ein Problem mit Ihrem Code sein, da Sie den Kern Ihres Programms außerhalb einer Funktion haben, also würde es laufen, sobald es importiert wird. Aus dem Grund (und anderen) sollten Sie alle Ihren Code in Funktionen haben. Sie können feststellen, ob der Code importiert wurde oder nicht, indem Sie das Attribut __main__ überprüfen.

Ich strukturierte Ihren Code neu, um den gesamten Code in Funktionen zu verschieben, dann importieren Sie ihn und rufen Sie die entsprechende Funktion über die GUI-Schaltflächen auf.

Dies ist, was Ihr GUI-Code soll wie folgt aussehen:

import tkinter 

import motionindexthreshold 
import motionindexgenerator 
import stepthrough 

def main(): 
    top=tkinter.Tk() 
    top.geometry("300x350") 
    top.config(background='black') 
    top.title('Test') 
    top.resizable(height=False, width=False) 

    M = tkinter.Message(top, text='Test', width=280, background='black', foreground='white', font=('Courier', 28)) 
    B = tkinter.Button(top,text="Define Motion Index Threshold",command=motionindexthreshold.main) 
    C = tkinter.Button(top,text="Autoremove Nonmovement Video Segments",command=motionindexgenerator.main) 
    D = tkinter.Button(top,text="Tag Video Frames",command=stepthrough.main) 
    E = tkinter.Button(top,text="Quit", command=top.destroy) 
    B.config(height=5, width=80, background='red') 
    C.config(height=5, width=80, background='blue', foreground='white') 
    D.config(height=5, width=80, background='yellow') 
    E.config(height=5, width=80, background='green') 
    M.pack() 
    B.pack() 
    C.pack() 
    D.pack() 
    E.pack() 
    top.mainloop() 

if __name__ == '__main__': 
    main() 

Und das ist, was Code Ihres Modul sollte wie folgt aussehen:

import cv2 
import tkinter as tk 
from tkinter.filedialog import askopenfilename 

def stanceTag(cap, framevalues):  
    framevalues.append('0' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def swingTag(cap, framevalues): 
    framevalues.append('1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def unsureTag(cap, framevalues): 
    framevalues.append('-1' + ' ' + '|' + ' ' + str(int(cap.get(1)))) 
    print (str(int(cap.get(1))), '/', length) 
    print(framevalues) 

def rewindFrames(cap, framevalues): 
    cap.set(1,((int(cap.get(1)) - 2))) 
    print (int(cap.get(1)), '/', length) 
    framevalues.pop() 
    print(framevalues) 


def main(): 
    framevalues = [] 
    count = 1 

    selectedvideo = askopenfilename() 
    selectedvideostring = str(selectedvideo) 
    cap = cv2.VideoCapture(selectedvideo) 
    length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) 

    while (cap.isOpened()): 
     ret, frame = cap.read() 

     # check if read frame was successful 
     if ret == False: 
       break 
     # show frame first 
     cv2.imshow('frame',frame) 

     # then waitKey 
     frameclick = cv2.waitKey(0) & 0xFF 

     if frameclick == ord('a'): 
      swingTag(cap, framevalues) 

     elif frameclick == ord('r'): 
      rewindFrames(cap, framevalues) 

     elif frameclick == ord('s'): 
      stanceTag(cap, framevalues) 

     elif frameclick == ord('d'): 
      unsureTag(cap, framevalues) 

     elif frameclick == ord('q'): 
      with open((selectedvideostring + '.txt'), 'w') as textfile: 
       for item in framevalues: 
        textfile.write("{}\n".format(item)) 
      break 

     else: 
      continue 

    cap.release() 
    cv2.destroyAllWindows() 

if __name__ == '__main__': 
    # this is called if this code was not imported ... ie it was directly run 
    # if this is called, that means there is no GUI already running, so we need to create a root 
    root = tk.Tk() 
    root.withdraw() 
    main() 

Offensichtlich ist dies eine Vermutung; Ich habe keine Möglichkeit zu testen, ob das dein Problem löst, aber ich denke es wird.

+1

Diese Antwort wäre viel besser, wenn Sie beschreiben könnten, was Sie geändert haben. Andernfalls muss das OP Ihre Lösung Zeile für Zeile mit dem Original vergleichen. –

+0

Vielen Dank, das ist wirklich hilfreich, und hat die meisten meiner Probleme behoben - nur ein Problem, wenn ich eine beliebige Taste drücken, um eine meiner Funktionen auszuführen, bekomme ich einen Namensfehler, dass 'framevalues' nicht definiert ist. Wie kann ich das beheben? Prost – KittenMittons

+0

Ah Ich habe übersehen, dass Sie das auch in Ihrer Funktion brauchen. Übergeben Sie es einfach wie 'Kappe'. Ich habe meine Antwort aktualisiert, um das zu zeigen. – Novel

Verwandte Themen