Interfaz con instrumentos usando Pyvisa -- python campo con beginner campo con python-3.x campo con error-handling campo con device-driver camp codereview Relacionados El problema

Interfacing with instruments using pyvisa


3
vote

problema

Español

Soy nuevo en Python, y después de pasar por algunos ejercicios de introducción, escribí una definición de clase para trabajar con algún hardware, específicamente un amplificador de lockin modelo 7230 de recuperación de señales. En los intereses de aprender buenos hábitos desde el principio, he intentado escribir "buen código" que está debidamente documentado, sigue las buenas prácticas y así sucesivamente.

  """ Module for  interfacing with Signal Recovery 7230 lock-in amplifier.  A substantial ammount is currently not implmented. It will not work with a lockin which is configured for double demodulation. If you get a lot of timeouts, that might be why.  It is also currently missing any way to configure the lockin. Use the web interface. It does read and expose the status bytes, but at the moment there is no checking of their content.  @author: Jack Barraclough """  import pyvisa   class WrongInstrumentError(Exception):     """The wrong instrument is connected      A connection was successfuly established, and the instrument responded     to a request to identify itself, but the ID recieved was wrong.     Probably the instrument at the given VISA identifier is not the one     you wanted.         """     pass   class Instrument:     """Represents a Signal Recovery Model 7230 lock-in amplifier      Note that several instances can be created representing the same     instrument. Be careful.     Instance variables:       pyvisa -- a pyvisa object for the connection, avoid using.       status_byte -- status byte after the last read operation.       overload_byte -- overload byte after the last read operation.     Methods:       read, write -- Read and write strings to/from the instrument.       get_X, get_Y, get_R, get_T -- get measurements from the instrument.       get_noise -- get the estimated measurement noise     """      def __init__(self,visaName):         """ Connects to the lockin amplifier          Connects to the lockin, and checks that the lockin is present and         correct. An error will be raised if the lockin is not there, or         if it fails to identify itself as a model 7230         Arguments:           visaName -- A Visa Resource ID, like 'TCPIP0::10.0.0.2::50000::SOCKET'         """         rm = pyvisa.ResourceManager()         self.pyvisa = rm.open_resource(visaName)         self.pyvisa.read_termination='0'         self.write('ID') # uses this not '*IDN?'         resp = self.read()         if resp != '7230':             raise WrongInstrumentError(                 'Wrote "ID" Expected "7230" got "{}"'.format(resp))      def write(self,string):         """Write string to the instrument."""         self.pyvisa.write(string)      def read(self):         """Read string from the instrument. Also sets status bytes"""         # replies seem to be: response LF NUL then two status bytes         resp = self.pyvisa.read().strip()         status = self.pyvisa.visalib.read(self.pyvisa.session,2)[0]         self.status_byte = status[0]         self.overload_byte = status[1]         return resp      def get_X(self):         """Get X value from the instrument, returns a float"""         self.write('X.')         return float(self.read())      def get_Y(self):         """Get Y value from the instrument, returns a float"""         self.write('Y.')         return float(self.read())      def get_R(self):         """Get R value from the instrument, returns a float"""         self.write('MAG.')         return float(self.read())      def get_T(self):         """Get theta value from the instrument, returns a float"""         self.write('PHA.')         return float(self.read())      def get_noise(self):         """Get Y noise from the instrument, in v/sqrtHz, returns a float"""         self.write('NHZ.')         return float(self.read())   

Estoy interesado en los comentarios generales, pero también tengo algunas preguntas específicas:

  1. ¿Estoy usando excepciones correctamente?
  2. El gerente de recursos de Pyvisa tiene un método 9988776655544331 . Al no llamarlo, ¿estoy fugando algo? ¿Se ocupará el coleccionista de basura? ¿Es mala forma dejarla al colector de basura? ¿Debo aclararlo con un destructor de alguna manera?
Original en ingles

I'm new to Python, and after running through some introductory exercises I wrote a class definition for working with some hardware, specifically a Signal Recovery model 7230 lockin amplifier. In the interests of learning good habits from the beginning, I've tried to write "good code" that is properly documented, follows good practices and so forth.

""" Module for  interfacing with Signal Recovery 7230 lock-in amplifier.  A substantial ammount is currently not implmented. It will not work with a lockin which is configured for double demodulation. If you get a lot of timeouts, that might be why.  It is also currently missing any way to configure the lockin. Use the web interface. It does read and expose the status bytes, but at the moment there is no checking of their content.  @author: Jack Barraclough """  import pyvisa   class WrongInstrumentError(Exception):     """The wrong instrument is connected      A connection was successfuly established, and the instrument responded     to a request to identify itself, but the ID recieved was wrong.     Probably the instrument at the given VISA identifier is not the one     you wanted.         """     pass   class Instrument:     """Represents a Signal Recovery Model 7230 lock-in amplifier      Note that several instances can be created representing the same     instrument. Be careful.     Instance variables:       pyvisa -- a pyvisa object for the connection, avoid using.       status_byte -- status byte after the last read operation.       overload_byte -- overload byte after the last read operation.     Methods:       read, write -- Read and write strings to/from the instrument.       get_X, get_Y, get_R, get_T -- get measurements from the instrument.       get_noise -- get the estimated measurement noise     """      def __init__(self,visaName):         """ Connects to the lockin amplifier          Connects to the lockin, and checks that the lockin is present and         correct. An error will be raised if the lockin is not there, or         if it fails to identify itself as a model 7230         Arguments:           visaName -- A Visa Resource ID, like 'TCPIP0::10.0.0.2::50000::SOCKET'         """         rm = pyvisa.ResourceManager()         self.pyvisa = rm.open_resource(visaName)         self.pyvisa.read_termination='\00'         self.write('ID') # uses this not '*IDN?'         resp = self.read()         if resp != '7230':             raise WrongInstrumentError(                 'Wrote "ID" Expected "7230" got "{}"'.format(resp))      def write(self,string):         """Write string to the instrument."""         self.pyvisa.write(string)      def read(self):         """Read string from the instrument. Also sets status bytes"""         # replies seem to be: response LF NUL then two status bytes         resp = self.pyvisa.read().strip()         status = self.pyvisa.visalib.read(self.pyvisa.session,2)[0]         self.status_byte = status[0]         self.overload_byte = status[1]         return resp      def get_X(self):         """Get X value from the instrument, returns a float"""         self.write('X.')         return float(self.read())      def get_Y(self):         """Get Y value from the instrument, returns a float"""         self.write('Y.')         return float(self.read())      def get_R(self):         """Get R value from the instrument, returns a float"""         self.write('MAG.')         return float(self.read())      def get_T(self):         """Get theta value from the instrument, returns a float"""         self.write('PHA.')         return float(self.read())      def get_noise(self):         """Get Y noise from the instrument, in v/sqrtHz, returns a float"""         self.write('NHZ.')         return float(self.read()) 

I'm interested in general feedback but also have some specific questions:

  1. Am I using exceptions correctly?
  2. The pyvisa resource manager has a rm.close() method. By not calling it, am I leaking something? Will the garbage collector deal with it? Is it bad form to leave it to the garbage collector? Should I clear it up with a destructor somehow?
              

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

Su código hasta ahora se ve bastante bien, bien estructurado, documentos de documentos útiles, bien hecho. Usted menciona excepciones; La única ocasión que lo usas me parece bien.


por la guía de estilo , por ejemplo array0 debe ser array1 . Además, en lugar de comentar array2 , es convencional para preparar los nombres de los atributos que no deben usarse externamente con un solo bajo costo: 99887776655443323 .


en lugar de incluir array4 En su documento, puede usar uno de los atributos del módulo especial de Python:

  array5  

array6 MÉTODOS DE no son muy Pythonic. En su lugar, le sugeriría que use propiedades, por ejemplo:

  array7  

Ahora, en lugar de array8 , puede escribir simplemente array9 .

Ir a más, hay mucha duplicación: cada una de las llamadas encoded_str0 luego devuelve el valor de encoded_str1 . Podrías factorizar esto completamente:

  encoded_str2  

Admito que no sé mucho sobre encoded_str3 , pero una opción para garantizar que el recurso es liberado sería hacer que su clase sea una Tipo de administrador de contexto . Entonces un usuario podría hacer por ejemplo.

  encoded_str4  

y asegúrate de que todo se tratara en encoded_str5 .

 

Your code so far looks pretty good - well structured, useful docstrings, well done! You mention exceptions; the one occasion you use it seems fine to me.


Per the style guide, e.g. visaName should be visa_name. Also, rather than commenting pyvisa -- a pyvisa object for the connection, avoid using., it is conventional to prepend the names of attributes that shouldn't be used externally with a single underscore: _pyvisa.


Rather than including @author in your docstring, you could use one of Python's special module attributes:

__author__ = 'Jack Barraclough' 

get methods aren't very Pythonic. Instead, I would suggest you use properties, for example:

@property def R(self):     """Get R value from the instrument, returns a float"""     self.write('MAG.')     return float(self.read()) 

Now, rather than instrument.get_R(), you can type simply instrument.R.

Going further, there is a lot of duplication - every single one calls self.write then returns the value from self.read. You could factor this out entirely:

class Instrument:      PROPERTIES = {'R': 'MAG.', ...}      def __getattr__(self, attr):         if attr in self.PROPERTIES:             return self._get(self.PROPERTIES[attr])         msg = "{!r} object has no attribute {!r}"         raise AttributeError(msg.format(self.__class__.__name__, attr))      def __setattr__(self, attr, val):         if attr in self.PROPERTIES:             raise AttributeError("can't set attribute")         return super().__setattr__(attr)      def _get(self, value):         self.write(value)         return float(self.read()) 

I admit I don't know much about pyvisa, but one option to ensure the resource is released would be to make your class a context manager type. Then a user could do e.g.

with Instrument(whatever) as inst:     ... 

and be certain that everything was dealt with on __exit__.

 
 
     
     
0
 
vote

No sé sobre pyvisa , pero tengo guiones muy similares para interfaz con instrumentos con VXI. En ese caso, el hablar se realiza a través de un zócalo TCP y no se cierre puede provocar problemas en la siguiente ejecución del script. Sin embargo, es posible que la Pyvisa se ocupe de estas cosas para usted. En mi caso usé un gerente de contexto para ello.

Dependiendo del instrumento, es posible que deba realizar el __setattr__ más complicado, ya que puede no solo leer, sino que también está cambiando algunas configuraciones en el instrumento. Probablemente necesitaría algunas listas como ReadOnly_PROPERTIES y ReadWrite_PROPERTIES3 .

@jonrsharpe No había visto antes de esa manera de definir un montón de propiedades en una sola visita. Idea impresionante! (Lamentablemente no tengo karma para upvote).

 

I don't know about pyvisa either, but I have pretty similar scripts to interface instruments with VXI. In that case, the talking is done through a tcp socket and not closing it may lead to problems on the next run of the script. However, it is possible the pyvisa takes care of these things for you. In my case I used a context manager for it.

Depending on the instrument you may need to make the __setattr__ more complicated, since you may be not only reading but also changing some settings in the instrument. Probably you would need a few lists like ReadOnly_PROPERTIES and ReadWrite_PROPERTIES.

@jonrsharpe I had not seen before that way of defining a bunch of properties in a single go. Awesome idea! (unfortunately I don't have karma to upvote).

 
 
 
 

Relacionados problema

11  Programa de abrelatas  ( Door opener program ) 
He estado trabajando en un pequeño proyecto en un Arduino y necesito ayuda para hacer que el código sea más eficiente / más limpio. Realmente no me gusta los ...

10  Incrustado C # bitpacked matrices al controlador STM32F4 de bajo nivel para GE G35 RGB LED LED de árbol de Navidad  ( Embedded c bitpacked arrays to low level stm32f4 driver for ge g35 rgb led chri ) 
Voy a ser opensurcing algún código en el que estoy trabajando. No necesito ayuda con el código, solo quiero asegurarme de que mi código sea legible y mis come...

2  Clase de entrada del teclado  ( Keyboard input class ) 
Estoy buscando consejos sobre mi componente de entrada. No hay ningún problema real con él, pero solo estoy empezando en todo y quiero saber si hay algún pro...

6  Bloqueo y comunicación UDP de ASYNC con una cámara IR  ( Blocking and async udp communication with an ir camera ) 
Estoy escribiendo una aplicación Java para controlar una cámara de investigación IR personalizada que se instalará en un avión. La cámara se conecta a la comp...

6  Generador de sincronización VGA para 640x480 @ 60Hz  ( Vga sync generator for 640x48060hz ) 
Escribí mi primer módulo en Verilog. El propósito es mantener dos mostradores y emitir señales correspondientes a los impulsos HSYNC y VSYNC de VGA, así como ...

5  Sistema de prueba automatizado  ( Automated test system ) 
Estoy creando un sistema de prueba automatizado (Alcance Bloat: la intención original fue una automatización de Bash única de un caso de prueba en particular ...

3  Mesa de búsqueda de Python  ( Python lookup table ) 
Estoy tratando de diseñar un protocolo para enviar / recibir datos en serie. El plan básico es permitir que los datos de texto se ingresen en el símbolo del...

3  Comandos de servo basados ​​en la entrada de puerto serie  ( Servo commands based on serial port input ) 
directamente al punto: ¿Puede darme punteros sobre cómo hacer que este código sea más mantenido? En el futuro, quiero agregar más cosas a esto, pero primero d...

5  Principios de programación - Lectura / escritura de / a una tarjeta MIFARE  ( Programming principles reading writing from to a mifare card ) 
Considere la siguiente clase (he eliminado el documento XML por el bien de la simplicidad), lo que hace varias operaciones y ligeramente diferentes a través d...

5  Comunicación TCP con motor de paso  ( Tcp communication with step motor ) 
Tengo un 9988776655544330 que uso para comunicarme con algunos equipos de hardware (un motor de paso para ser preciso): public class HdCommunicator : IDi...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos