Kivy & pyvisa - 如何在 GPIB 连接后将 ObjectProperty 设置为 None?

Posted

技术标签:

【中文标题】Kivy & pyvisa - 如何在 GPIB 连接后将 ObjectProperty 设置为 None?【英文标题】:Kivy & pyvisa - How to make an ObjectProperty to None after a GPIB connection? 【发布时间】:2021-03-21 17:40:54 【问题描述】:

我正面临 kivy 和 pyvisa 的真正阻塞问题,我真的不知道如何找到解决方案。

在下面的代码中,我有一个名为“device”的 ObjectProperty,它被初始化为 None。我想用它来启动 GPIB 连接。当这个关闭时,我想再次将设备属性设置为无。

下面的所有代码都是尝试找到解决此问题的简单示例,但实际上我在实际应用程序中遇到了这个问题。此应用程序的功能之一是在列表中选择要使用的设备,我无法提前知道哪个设备可用或不可用,或者即使属性“设备”将在 GPIB 中连接或在另一个协议中。这就是为什么将它重置为无对我来说很重要的原因。

代码如下:

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 连接和断开设备时,一切正常,但是当我尝试使“设备”在断开连接后返回 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

所以,我真的不明白为什么它不起作用...... 有没有人知道如何解决这个问题?

注意:这是我在这里的第一篇文章,所以我希望所有内容都得到清楚的解释并且我没有犯错^^如果是这样,请告诉我!

【问题讨论】:

【参考方案1】:

https://kivy.org/doc/stable/api-kivy.properties.html#kivy.properties.Property

None 是一种特殊情况:您可以将 Property 的默认值设置为 None,但以后不能将 None 设置为属性。如果你真的想这样做,你必须用 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 - 如何在 GPIB 连接后将 ObjectProperty 设置为 None?的主要内容,如果未能解决你的问题,请参考以下文章

PyVISA - 无法让 GPIB 仪器以编程方式进入远程模式

在子小部件中,如何在 kivy 中获取父小部件的实例

Keithley 2410 和 PyVISA - VI_ERROR_TMO:在操作完成前超时

PyVISA介绍

Anritsu PyVISA 问题

PyVISA RS232 超时错误(安捷伦电源)