此样本来自我正在进行的项目。我的客户使用的软件使用他的网络摄像头拍摄快照,如果在其视图中检测到运动。问题是,软件无法在拍摄时将图像通过电子邮件发送到他的帐户。我编写了这个项目来监视保存快照的文件夹,并将其设置为将电子邮件中的任何新快照发送到定义的帐户,这样他就会在发生的情况下收到关于他的单元格的警报以及快照什么被抓住了。是的我知道有很多应用程序在他们的网络摄像头软件中包含此功能,但我的客户已雇用我,因此他可以避免在他习惯使用时更换他当前的软件。
Start()函数有两个步骤。步骤1是监视器启动之前的延迟,步骤2是监视器本身的启动。到目前为止,我无法使用Stop()函数从GUI的statusBar中倒数第1步。
Monitor.Stop()函数在控制台中单独运行时工作正常,但是当它从界面中的self.OnConnect()事件处理程序中运行时它不起作用?我尝试使用多种线程结构变体:线程,线程,kthread等,但都以相同的结果结束。
理想情况下,我想点击文件菜单下的连接 - >将标签更改连接到Disconnect - >监视器从步骤1开始 - > statusBar显示第2步之前的剩余时间。
此时我希望能够通过点击“文件”菜单下的“断开连接”来停止倒计时,但是当我点击它时倒计时继续进行?我尝试过的线程函数的每个变体都在从控制台中运行时成功停止了线程,但到目前为止我还无法弄清楚为什么倒计时在我的gui中调用时无法停止?
任何帮助将不胜感激! :d
顺便说一句,如果您选择运行它,请确保将脚本底部的两个“C:\ Replace \ With \ Valid \ Path”条目替换为系统上的有效路径。
import os, sys, thread, time, wx
class Frame(wx.Frame):
def __init__(self, parent, id=-1, title="A Frame", path="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self.path = path
self.StatusBar = wx.StatusBar(self, -1)
self.StatusBar.SetFieldsCount(3)
self.StatusBar.SetStatusWidths([-2, -1, -1])
self.InitMenuBar()
def InitMenuBar(self):
menuBar = wx.MenuBar()
menuFile = wx.Menu()
menuHelp = wx.Menu()
self._Connect = menuFile.Append(101, "&Connect", kind=wx.ITEM_CHECK)
menuFile.AppendSeparator()
menuFile.Append(104, "E&xit")
menuBar.Append(menuFile, "&File")
menuBar.Append(menuHelp, "&Help")
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.OnConnect, self._Connect)
def OnConnect(self, event):
#print [event.IsChecked()]
mon = Monitor("", "", "", self.path, "60", self.StatusBar)
if event.IsChecked():
print "Set Menu Label Disconnected"
self._Connect.SetItemLabel("Disconnect")
print "Start Monitor"
mon.Start()
print "Start Finished"
else:
print "Set Menu Label Connected"
self._Connect.SetItemLabel("Connect")
print "Stop Monitor"
mon.Stop()
print "Stop Finished"
class Monitor:
def __init__(self, email, password, recipient, path, timeout, statusBar=None):
self.email = email
self.password = password
self.recipient = recipient
self.path = path
self.timeout = timeout
self.statusBar = statusBar
#self.lock = thread.allocate_lock()
def Start(self):
#self.lock.acquire()
self.running = True
thread.start_new_thread(self.Run, ())
#self.lock.release()
def Stop(self):
#self.lock.acquire()
self.running = False
#self.lock.release()
def IsRunning(self):
return self.running
def Run(self):
start = NewestByModTime(self.path)
count = int(self.timeout)
while self.running:
#print self.running
# Step 1 - Delay the start of the monitor for X amount of seconds, updating the
# statusbar/console each second to relfect a countdown. remove one from count each
# loop until the count equals 0, than continue on to Step 2.
if count > 0:
if self.statusBar:
self.statusBar.SetStatusText("Monitoring will begin in %s seconds" % (count))
else:
sys.stdout.write("Monitoring will begin in %s seconds\r" % (count))
#sys.stdout.flush()
count -= 1
time.sleep(1)
# Step 2 - Start the monitor function which monitors the selected folder for new
#files. If a new file is detected, send notification via email with the new file
#as an attachment. (for this project, files in the folder will always be jpg images)
# *NOTE* I Have not tested the Stop() function during Step 2 just yet, but I would
# assume it would fail just the same as . *NOTE*
if count == 0:
current = NewestByModTime(self.path)
if current[1] > start[1]:
print "Activity Detected"
start = current
print "Sending Notification Email"
#sendMail(self.email, self.password, self.recipient, "JERK ALERT!!",
# "Some jerkoff is in your place right now, wanna see who it is??", "%s\\%s" % (self.path, start[0]))
print "Notification Email Sent!"
print
self.running = False
def NewestByModTime(path):
stat = ["", 0]
for a in os.listdir(path):
new = os.path.getmtime("%s\\%s" %(path, a))
if new > stat[1]:
stat = [a, new]
return stat
if __name__ == "__main__":
# Run GUI
app = wx.PySimpleApp()
frame = Frame(None, -1, "Test Frame", "C:\\Replace\\With\\Valid\\Path", size=(800, 600))
frame.Show()
app.MainLoop()
del app
## Run Console
#mon = Monitor("", "", "", "C:\\Replace\\With\\Valid\\Path", "60", None)
#mon.Start()
#time.sleep(10)
#mon.Stop()
答案 0 :(得分:0)
刚想通了..为什么我最大的问题总是一线修复? :P
显然我忽略了每次调用 self.OnConnect 时我正在重新创建变量 mon 这一事实当我沮丧到足以疯狂地点击连接/断开十亿次并观察不同倒计时59,43,58,42等之间的计数器交换时,我有点想知道这个错误.LOL
我将mon更改为self.mon并添加 if if hasattr(self,“mon”) 以阻止 self.mon 每次重新创建自己。到目前为止,问题已经解决,倒计时完全停止。
def OnConnect(self, event):
#print [event.IsChecked()]
mon = Monitor("", "", "", self.path, "60", self.StatusBar)
if event.IsChecked():
print "Set Menu Label Disconnected"
self._Connect.SetItemLabel("Disconnect")
print "Start Monitor"
mon.Start()
print "Start Finished"
else:
print "Set Menu Label Connected"
self._Connect.SetItemLabel("Connect")
print "Stop Monitor"
mon.Stop()
print "Stop Finished"
要:
def OnConnect(self, event):
#print [event.IsChecked()]
if not hasattr(self, "mon"):
self.mon = Monitor("", "", "", self.path, "60", self.StatusBar)
if event.IsChecked():
print "Set Menu Label Disconnected"
self._Connect.SetItemLabel("Disconnect")
print "Start Monitor"
self.mon.Start()
print "Start Finished"
else:
print "Set Menu Label Connected"
self._Connect.SetItemLabel("Connect")
print "Stop Monitor"
self.mon.Stop()
print "Stop Finished"