Kivy & pyvisa - 如何在 GPIB 连接后将 ObjectProperty 设置为 None?
Kivy & pyvisa - How to make an ObjectProperty to None after a GPIB connection?
我正面临 kivy 和 pyvisa 的真正阻塞问题,我真的不知道如何找到解决方案。
在下面的代码中,我有一个名为 'device' 的 ObjectProperty,它被初始化为 None。我想用它来启动 GPIB 连接。当这个关闭时,我想再次将设备属性设置为None。
下面的所有代码都是一个简单的例子,试图找到解决这个问题的方法,但我在实际应用程序中确实遇到了这个问题。这个应用程序的功能之一是在列表中选择要使用的设备,我不可能提前知道哪一个可用或不可用,甚至 属性 'device'将在 GPIB 或其他协议中连接。这就是为什么将其重置为 None.
对我来说很重要
代码如下:
main.py
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.properties import ObjectProperty, BooleanProperty, StringProperty
from pyvisa import ResourceManager
class NoneScreen(Screen):
# Properties
address = StringProperty('GPIB0::10::INSTR')
isConnected = BooleanProperty(False)
device = ObjectProperty(None)
# Connect/Disconnect very basicaly to a GPIB device
def connect(self):
if not self.isConnected:
print('Connect to', self.address)
rm = ResourceManager()
self.device = rm.open_resource(self.address)
self.isConnected = True
else:
print('Disconnect from', self.address)
self.device.close()
self.isConnected = False
# Test the state of the connection
def testCon(self):
try:
self.device.query('*IDN?')
except:
print('You are not connected')
else:
print('You are connected :)')
# Try something to make device properties None again
def noneFct(self):
self.device = None
# App
class MainApp(App):
def build(self):
ns = NoneScreen()
return ns
if __name__ == '__main__':
MainApp().run()
Main.kv
<NoneScreen>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Print'
on_release: print('self.device =', root.device)
Button:
text: 'Connect'
on_release: root.connect()
Button:
text: 'Test Connexion'
on_release: root.testCon()
Button:
text: 'Become None'
on_release: root.noneFct()
所以,这是我的问题:当我从 GPIB 连接和断开设备时,一切都进行得很顺利,但是当我尝试在 'device' return 到 None 之后断开连接我有这个错误:
self.device = None
Connect to GPIB0::10::INSTR
You are connected :)
self.device = GPIBInstrument at GPIB0::10::INSTR
Disconnect from GPIB0::10::INSTR
self.device = GPIBInstrument at GPIB0::10::INSTR
You are not connected
[INFO ] [Base ] Leaving application in progress...
Traceback (most recent call last):
File "C:\Users\Frederic\Desktop\debug\main.py", line 51, in <module>
MainApp().run()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\app.py", line 855, in run
runTouchApp()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 504, in runTouchApp
EventLoop.window.mainloop()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 747, in mainloop
self._mainloop()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 479, in _mainloop
EventLoop.idle()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 342, in idle
self.dispatch_input()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 327, in dispatch_input
post_dispatch_input(*pop(0))
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 293, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
exec(__kvlang__.co_value, idmap)
File "C:\Users\Frederic\Desktop\debug\main.kv", line 20, in <module>
on_release: root.noneFct()
File "C:\Users\Frederic\Desktop\debug\main.py", line 38, in noneFct
self.device = None
File "kivy\properties.pyx", line 497, in kivy.properties.Property.__set__
File "kivy\properties.pyx", line 541, in kivy.properties.Property.set
File "kivy\properties.pyx", line 532, in kivy.properties.Property.set
File "kivy\properties.pyx", line 1001, in kivy.properties.ObjectProperty.check
File "kivy\properties.pyx", line 570, in kivy.properties.Property.check
ValueError: None is not allowed for NoneScreen.device
所以,这就是为什么它对我来说很奇怪:如果我尝试做同样的事情,而不使用 kivy,在 python 命令行中,它有效!
>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> device = None
>>> print(device)
None
>>> device = rm.open_resource('GPIB0::10::INSTR')
>>> print(device)
GPIBInstrument at GPIB0::10::INSTR
>>> device.query('*IDN?')
'Agilent Technologies,33250A,0,2.01-1.01-1.00-03-2\n'
>>> device.close()
>>> print(device)
GPIBInstrument at GPIB0::10::INSTR
>>> device = None
>>> print(device)
None
所以,我真的不明白为什么它不起作用...
有人知道如何解决这个问题吗?
N.B : 这是我第一次 post 在这里,所以我希望所有的解释都清楚并且我没有犯错 ^^ 如果是这样的话请告诉我!
https://kivy.org/doc/stable/api-kivy.properties.html#kivy.properties.Property
None是一个特例:可以将a属性的默认值设置为None,但不能将None设置为a属性 之后。如果你真的想这样做,你必须声明 属性 with allownone=True:
class MyObject(Widget):
hello = ObjectProperty(None, allownone=True)
# then later
a = MyObject()
a.hello = 'bleh' # working
a.hello = None # working too, because allownone is True.
改变
device = ObjectProperty(None)
到
device = ObjectProperty(None, allownone=True)
我正面临 kivy 和 pyvisa 的真正阻塞问题,我真的不知道如何找到解决方案。
在下面的代码中,我有一个名为 'device' 的 ObjectProperty,它被初始化为 None。我想用它来启动 GPIB 连接。当这个关闭时,我想再次将设备属性设置为None。
下面的所有代码都是一个简单的例子,试图找到解决这个问题的方法,但我在实际应用程序中确实遇到了这个问题。这个应用程序的功能之一是在列表中选择要使用的设备,我不可能提前知道哪一个可用或不可用,甚至 属性 'device'将在 GPIB 或其他协议中连接。这就是为什么将其重置为 None.
对我来说很重要代码如下:
main.py
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.properties import ObjectProperty, BooleanProperty, StringProperty
from pyvisa import ResourceManager
class NoneScreen(Screen):
# Properties
address = StringProperty('GPIB0::10::INSTR')
isConnected = BooleanProperty(False)
device = ObjectProperty(None)
# Connect/Disconnect very basicaly to a GPIB device
def connect(self):
if not self.isConnected:
print('Connect to', self.address)
rm = ResourceManager()
self.device = rm.open_resource(self.address)
self.isConnected = True
else:
print('Disconnect from', self.address)
self.device.close()
self.isConnected = False
# Test the state of the connection
def testCon(self):
try:
self.device.query('*IDN?')
except:
print('You are not connected')
else:
print('You are connected :)')
# Try something to make device properties None again
def noneFct(self):
self.device = None
# App
class MainApp(App):
def build(self):
ns = NoneScreen()
return ns
if __name__ == '__main__':
MainApp().run()
Main.kv
<NoneScreen>:
BoxLayout:
orientation: 'vertical'
Button:
text: 'Print'
on_release: print('self.device =', root.device)
Button:
text: 'Connect'
on_release: root.connect()
Button:
text: 'Test Connexion'
on_release: root.testCon()
Button:
text: 'Become None'
on_release: root.noneFct()
所以,这是我的问题:当我从 GPIB 连接和断开设备时,一切都进行得很顺利,但是当我尝试在 'device' return 到 None 之后断开连接我有这个错误:
self.device = None
Connect to GPIB0::10::INSTR
You are connected :)
self.device = GPIBInstrument at GPIB0::10::INSTR
Disconnect from GPIB0::10::INSTR
self.device = GPIBInstrument at GPIB0::10::INSTR
You are not connected
[INFO ] [Base ] Leaving application in progress...
Traceback (most recent call last):
File "C:\Users\Frederic\Desktop\debug\main.py", line 51, in <module>
MainApp().run()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\app.py", line 855, in run
runTouchApp()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 504, in runTouchApp
EventLoop.window.mainloop()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 747, in mainloop
self._mainloop()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\core\window\window_sdl2.py", line 479, in _mainloop
EventLoop.idle()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 342, in idle
self.dispatch_input()
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 327, in dispatch_input
post_dispatch_input(*pop(0))
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\base.py", line 293, in post_dispatch_input
wid.dispatch('on_touch_up', me)
File "kivy\_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\uix\behaviors\button.py", line 179, in on_touch_up
self.dispatch('on_release')
File "kivy\_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
File "kivy\_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
File "C:\Users\Frederic\AppData\Local\Programs\Python\Python37\lib\site-packages\kivy\lang\builder.py", line 64, in custom_callback
exec(__kvlang__.co_value, idmap)
File "C:\Users\Frederic\Desktop\debug\main.kv", line 20, in <module>
on_release: root.noneFct()
File "C:\Users\Frederic\Desktop\debug\main.py", line 38, in noneFct
self.device = None
File "kivy\properties.pyx", line 497, in kivy.properties.Property.__set__
File "kivy\properties.pyx", line 541, in kivy.properties.Property.set
File "kivy\properties.pyx", line 532, in kivy.properties.Property.set
File "kivy\properties.pyx", line 1001, in kivy.properties.ObjectProperty.check
File "kivy\properties.pyx", line 570, in kivy.properties.Property.check
ValueError: None is not allowed for NoneScreen.device
所以,这就是为什么它对我来说很奇怪:如果我尝试做同样的事情,而不使用 kivy,在 python 命令行中,它有效!
>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> device = None
>>> print(device)
None
>>> device = rm.open_resource('GPIB0::10::INSTR')
>>> print(device)
GPIBInstrument at GPIB0::10::INSTR
>>> device.query('*IDN?')
'Agilent Technologies,33250A,0,2.01-1.01-1.00-03-2\n'
>>> device.close()
>>> print(device)
GPIBInstrument at GPIB0::10::INSTR
>>> device = None
>>> print(device)
None
所以,我真的不明白为什么它不起作用... 有人知道如何解决这个问题吗?
N.B : 这是我第一次 post 在这里,所以我希望所有的解释都清楚并且我没有犯错 ^^ 如果是这样的话请告诉我!
https://kivy.org/doc/stable/api-kivy.properties.html#kivy.properties.Property
None是一个特例:可以将a属性的默认值设置为None,但不能将None设置为a属性 之后。如果你真的想这样做,你必须声明 属性 with allownone=True:
class MyObject(Widget):
hello = ObjectProperty(None, allownone=True)
# then later
a = MyObject()
a.hello = 'bleh' # working
a.hello = None # working too, because allownone is True.
改变
device = ObjectProperty(None)
到
device = ObjectProperty(None, allownone=True)