Using visa to interface with GPIB always gives me VisaIOError - python

I'm trying to import visa in Python and interface with GPIB to control a device.
The name of device I'm using is "GPIB0::9::INSTR", and I think there should be no problem with this.
I ran the following code in 2.7.3 Python Shell
>>> from visa import *
>>> a = instrument("GPIB0::9", timeout = 20)
>>> a.write("*IDN?")
>>> print a.read()
Traceback (most recent call last):
File "<pyshell#53>", line 1, in <module>
print a.read()
File "C:\Python27\lib\site-packages\pyvisa\visa.py", line 433, in read
return self._strip_term_chars(self.read_raw())
File "C:\Python27\lib\site-packages\pyvisa\visa.py", line 407, in read_raw
chunk = vpp43.read(self.vi, self.chunk_size)
File "C:\Python27\lib\site-packages\pyvisa\vpp43.py", line 840, in read
visa_library().viRead(vi, buffer, count, byref(return_count))
File "C:\Python27\lib\site-packages\pyvisa\vpp43.py", line 398, in check_status
raise visa_exceptions.VisaIOError, status
VisaIOError: VI_ERROR_TMO: Timeout expired before operation completed.
Above is the error the system gave me.
Actually at the beginning, I set the Timeout to be 3, it shows this errot. But after I changed the value to be 20 as shown above, it still didn't work.
Can somebody help me?

There are different problems that could lead to a timeout.
First you should check if your device supports the *IDN?query. It is a IEEE-488.2 standard command, so chances are high it is supported (if not check your manual for commands that are).
Then you should check you're communication settings, specifically the termination character and the EOI.
If you're using the wrong termination character, visa will keep on reading and finally time out.
Note: You can use pyvisa's ask function if you're using a queryable command (it is a combined write and read).
import visa
# If you've got just one gpib card installed, you can ommit the 0.
# ASsuming the EOI line should be asserted and a termination character
# of '\n'
instrument = visa.instrument('GPIB::9', term_chars='\n', send_end=True)
# use ask to write the command and read back the response
print instrument.ask('*IDN?')

import visa
rm = visa.ResourceManager()
devices = rm.list_resources()
comm_channel = rm.open_resource(devices[0]) #assuming you only have 1 address to worry about
print(comm_channel.query("*IDN?"))
This exploits PYVisa's module and the many functions it has to offer with connecting/writing/reading to and from a USB/GPIB device.

For each one specific instruments, it will have its own command to control them. Please refer to the device's user manual.

Related

Why isn't my code working in command line?

I am using Python3.6 and I need to run my code in command line. The code works when I run it in PyCharm but when I use command line I get this error:
File "path", line 43, in <module>
rb = ds.GetRasterBand(1)
AttributeError: 'NoneType' object has no attribute 'GetRasterBand'
It seems that I have a problem with these lines:
ds = gdal.Open('tif_file.tif', gdal.GA_ReadOnly)
rb = ds.GetRasterBand(1)
img_array = rb.ReadAsArray()
Does anyone know what I might have done wrong?
EDIT
Some magic just happened. I tried to run my code this morning and everything seems fine. I guess what my computer needed was a restart or something. Thanks to you all for help.
from the gdal documentation:
from osgeo import gdal
dataset = gdal.Open(filename, gdal.GA_ReadOnly)
if not dataset:
...
Note that if GDALOpen() returns NULL it means the open failed, and
that an error messages will already have been emitted via CPLError().
If you want to control how errors are reported to the user review the
CPLError() documentation. Generally speaking all of GDAL uses
CPLError() for error reporting. Also, note that pszFilename need not
actually be the name of a physical file (though it usually is). It's
interpretation is driver dependent, and it might be an URL, a filename
with additional parameters added at the end controlling the open or
almost anything. Please try not to limit GDAL file selection dialogs
to only selecting physical files.
looks like the file you are trying to open is not a valid gdal file or some other magic is going on in the file selection. you could try to direct the program to a known good file online to test it.

Typeerror: Unicode strings are not supported, please encode to bytes: 'ÿ'

I have found this code (https://drive.google.com/open?id=1TGuTPjfiV4r7ra_5eLMkbXBnesYlvTyT) written by Adafruit (and modified by me to add in a few extra features which work in python 2.7, when I try to run the code in python 3 to make it easier to develop (as I haven't looked at much python 2 before) it gives me the error:
Traceback (most recent call last):
File "/home/pi/Forecast-Printer/forecast.py", line 55, in <module>
printer = Adafruit_Thermal("/dev/serial0", 19200, timeout=5)
File "/home/pi/Forecast-Printer/Adafruit_Thermal.py", line 95, in __init__
self.wake()
File "/home/pi/Forecast-Printer/Adafruit_Thermal.py", line 605, in wake
self.writeBytes(255)
File "/home/pi/Forecast-Printer/Adafruit_Thermal.py", line 189, in writeBytes
super(Adafruit_Thermal, self).write(chr(arg))
File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 518, in write
d = to_bytes(data)
File "/usr/lib/python3/dist-packages/serial/serialutil.py", line 63, in to_bytes
raise TypeError('unicode strings are not supported, please encode to bytes: {!r}'.format(seq))
TypeError: unicode strings are not supported, please encode to bytes: 'ÿ'
The code is run on a raspberry pi running raspbian (GUI version) and it needs to be run with sudo as it communicates with the mini thermal printer via serial.
Thanks in advance for any help :)
edit:
Here is some code that triggers the same error when run in python 3:
from Adafruit_Thermal import *
printer = Adafruit_Thermal("/dev/serial0", 19200, timeout=5)
From the stack trace it looks like when the printer is initialized, the Adafruit library wakes up the printer by writing the integer 255 over serial to the printer. It does this by calling the Serial class's write() method (inside its own write_bytes() method) on line 189:
super(Adafruit_Thermal, self).write(chr(arg))
It's able to do this since the Adafruit_Thermal class inherits from Serial, as you can see in the class definition.
Well as #abarnert pointed out, chr() returns a string, but it sounds like write() is expecting binary data. So I'd try both the suggestions in the comments to your question. First try changing line 189 to:
super(Adafruit_Thermal, self).write(arg)
If that doesn't work try:
super(Adafruit_Thermal, self).write(bytes([arg]))

Python poplib error_proto: line too long

Recently, without changes to codes/libs, I started getting python error_proto: line too long error when reading email (poplib.retr) from hotmail inbox. I am using Python version 2.7.8. I understand that a long line may be caused this error. But is there a way to go around this or a certain version I need to put in place. Thank you for any advice/direction anyone can give.
Here is a traceback error:
"/opt/rh/python27/root/usr/lib64/python2.7/poplib.py", line 232, in retr\n return self._longcmd(\'RETR %s\' % which)\n',
' File "/opt/rh/python27/root/usr/lib64/python2.7/poplib.py", line 167, in _longcmd\n return self._getlongresp()\n',
' File "/opt/rh/python27/root/usr/lib64/python2.7/poplib.py", line 152, in _getlongresp\n line, o = self._getline()\n',
' File "/opt/rh/python27/root/usr/lib64/python2.7/poplib.py", line 377, in _getline\n raise error_proto(\'line too long\')\n',
'error_proto: line too long\n'
A python bug report exists for this issue here: https://bugs.python.org/issue16041
The work around I put inplace was as follows:
import poplib
poplib._MAXLINE=20480
I thought this was a better idea, rather than editing the poplib.py library file directly.
Woody
Are you sure you've not updated poplib? Have a look at the most recent diff, committed last night:
# Added:
...
# maximal line length when calling readline(). This is to prevent
# reading arbitrary length lines. RFC 1939 limits POP3 line length to
# 512 characters, including CRLF. We have selected 2048 just to be on
# the safe side.
_MAXLINE = 2048
...
# in_getline()...
if len(self.buffer) > _MAXLINE:
raise error_proto('line too long')
...it looks suspiciously similar to your problem.
So if you roll back to the previous version, it will probably be OK.

Error on Pytz - IndexError: list index out of range

I'm having this problem with ptyz:
>>> import pytz
>>> pytz.timezone('US/Mountain')
Traceback (most recent call last):
File "stdin", line 1, in module
File "/home/user/.local/lib/python2.6/site-packages/pytz-2013b-py2.6.egg/pytz/__init__.py", line 181, in timezone
_tzinfo_cache[zone] = build_tzinfo(zone, fp)
File "/home/user/.local/lib/python2.6/site-packages/pytz-2013b-py2.6.egg/pytz/tzfile.py", line 78, in build_tzinfo
while ttinfo[i][1]:
IndexError: list index out of range
I have two accounts in a server, and two different installations of pytz, though they are a copy of each other. In one of them, pytz works as a charm, but in the other one I have this error. It looks like an error inside ptyz, but it cannot be, because pytz works fine in the other account.
Has anyone handled this befor or have any idea of what may be causing this?
Update:
This error just happen when the script is called by a page, and that's the exact last message:
build_tzinfo(zone='US/Michigan', fp=<closed file '/home/user/.local/lib/python2...e-packages/pytz/zoneinfo/US/Michigan', mode 'rb'>)
and fp is a variable inside init.py that just receives it:
open(filename, 'rb')
It seems that the file is found, opened, but not really opened. I found at http://docs.python.org/2/tutorial/inputoutput.html that there are differences between linux and windows on the way they see binary files. My server runs Linux and, again, on the other account, with the same instalation, pytz works as a charm.
That's what happened:
After I updated my question, I noticed that the problem was with python opening a binary file. A friend told me to check the software I was using to send files to the server (Filezila), and there was three types of transfer: ASCII, Binary or Automatic. The software was set to Automatic. I send again the binary files in the binary transfer mode and it worked.

Is it possible to get writing access to raw devices using python with windows?

This is sort of a follow-up to this question. I want to know if you can access raw devices (i.e. \\.\PhysicalDriveN) in writing mode and if this should be the case, how.
Using Linux, write access can simply be achieved by using e.g. open("/dev/sdd", "w+") (provided that the script is running with root permissions). I assume that Mac OS behaves similar (with /dev/diskN as input file).
When trying the same command under Windows (with the corresponding path), it fails with the following error:
IOError: [Errno 22] invalid mode ('w+') or filename: '\\\\.\\PhysicalDrive3'
However, when trying to read from the PhysicalDrive, it does work (even the correct data is read). The shell is running with administrator permissions under Windows 7.
Is there any other way to accomplish this task using python while still keeping the script as platform-independent as possible?
Edit:
I looked a bit further into what methods python provides for file handling and stumbled across os.open. Opening the PhysicalDrive using os.open(drive_string, os.O_WRONLY|os.O_BINARY) returns no error. So far, so good. Now I have either the choice to write directly to this file-descriptor using os.write, or use os.fdopen to get a file-object and write to it in the regular way.
Sadly, none of these possibilities works. In the first case (os.write()), I get this:
>>> os.write(os.open("\\\\.\\PhysicalDrive3", os.O_WRONLY|os.O_BINARY), "test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
In the second case, I can create a file object with write permissions, but the writing itself fails (well, after enforcing its execution using .flush()):
>>> g = os.fdopen(os.open("\\\\.\\PhysicalDrive3", os.O_WRONLY|os.O_BINARY), "wb")
>>> g.write("test")
>>> g.flush()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument
As eryksun and agf pointed out in the comments (but I didn't really get it at first), the solution is rather simple: you have to open the device in the rb+ mode, which opens the device for updating (as I have found out now..) without trying to replace it with a new file (which wouldn't work because the file is in fact a physical drive).
When writing, you have to write always a whole sector at a time (i.e. multiples of 512-byte), otherwise it fails.
In addition, the .seek() command can also jump only sector-wise. If you try to seek a position inside a sector (e.g. position 621), the file object will jump to the beginning of the sector where your requested position is (i.e. to the beginning of the second sector, byte 512).
Possibly in Win 7 you have to do something more extreme, such as locking the volume(s) for the disk beforehand with DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, ...)
In Win 7 you don't have to do that; opening and writing with 'rb+' mode works fine.

Categories