As we move towards using Python 3, I have encountered a problem related to
the MetaArrays. Although not related to the graphics portion of pyqtgraph,
MetaArrays are part of pyqtgraph. I suspect they are not widely used, but
they are used extensively in acq4 (a separate project that depends on
pyqtgraph).
MetaArrays written in Python 2 or Python 3 are readable in Python 2.
However, neither seems to be readable in Python 3. This seems to be
related to the difference between strings and bytes in the two when
interpreting part of the data.
The specific error (test script of minimal working version is attached; see
the code for usage) is:
user: sandbox $ python test_ma.py read 2
Running under Python 3: 3.6.5
Reading metaarray_py2.ma
Traceback (most recent call last):
File "test_ma.py", line 57, in <module>
mdata = ma.MetaArray(file=fn)
File
"/Users/pbmanis/Desktop/Python/pyqtgraph/pyqtgraph/metaarray/MetaArray.py",
line 135, in __init__
self.readFile(file, **kwargs)
File
"/Users/pbmanis/Desktop/Python/pyqtgraph/pyqtgraph/metaarray/MetaArray.py",
line 752, in readFile
meta = MetaArray._readMeta(fd)
File
"/Users/pbmanis/Desktop/Python/pyqtgraph/pyqtgraph/metaarray/MetaArray.py",
line 777, in _readMeta
meta += line
*TypeError: must be str, not bytes*
user: sandbox $ python test_ma.py read 3
Running under Python 3: 3.6.5
Reading metaarray_py3.ma
Traceback (most recent call last):
File "test_ma.py", line 57, in <module>
mdata = ma.MetaArray(file=fn)
File
"/Users/pbmanis/Desktop/Python/pyqtgraph/pyqtgraph/metaarray/MetaArray.py",
line 135, in __init__
self.readFile(file, **kwargs)
File
"/Users/pbmanis/Desktop/Python/pyqtgraph/pyqtgraph/metaarray/MetaArray.py",
line 752, in readFile
meta = MetaArray._readMeta(fd)
File
"/Users/pbmanis/Desktop/Python/pyqtgraph/pyqtgraph/metaarray/MetaArray.py",
line 777, in _readMeta
meta += line
*TypeError: must be str, not bytes*
Whereas in Python 2 we can read or write python 2 or 3 files just fine.
user: sandbox $ python test_ma.py read 3
Running under Python 2: 2.7.14
user metaarray_py3.ma (displays data)
The problem lies in this routine around line 777 in MetaArray.py:
@staticmethod
def _readMeta(fd):
"""Read meta array from the top of a file. Read lines until a blank
line is reached.
This function should ideally work for ALL versions of MetaArray.
"""
meta = ''
## Read meta information until the first blank line
while True:
line = fd.readline().strip()
if line == '':
break
meta += line
ret = eval(meta)
#print ret
return ret
I have tried to clean this up to be agnostic with respect to python
versions, but without success. I suspect there is a simple way to do this,
but I haven't found it yet.
Any ideas?
--Paul
--
You received this message because you are subscribed to the Google Groups
"pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/pyqtgraph/a763c66e-dd2d-4715-a605-d5417c921b6c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
from __future__ import print_function
"""
Test metaarrays for python 2.7 versus 3.5+
Usage:
First, generate the .ma file from the version of Python you are running, and switch versions/enviornments and generate the other test file
>python test_ma.py write 2 (note the write code will generate the file appropriate for the version you are running under).
Then, try to read:
python test_ma.py read 2 (or read 3)
"""
import sys
import platform
import numpy as np
import pyqtgraph.metaarray as ma
import matplotlib.pyplot as mpl
if len(sys.argv) == 3:
mode = sys.argv[1]
version = sys.argv[2]
else:
print('Call: python test_ma.py [read | write] [2|3]')
print('must specify read or write (which also does read) for the .ma file')
print( sys.argv)
exit(1)
if mode not in ['read', 'write']:
raise ValueError('Mode must be read or write')
if version not in ['2', '3']:
raise ValueError ('version must be 2 or 3')
if sys.version_info[0] == 2:
print('Running under Python 2: ', platform.python_version())
elif sys.version_info[0] == 3:
print('Running under Python 3: ', platform.python_version())
if mode == 'write':
print('Writing .ma file')# create a metaarray file on disk (problem is reading py2 files in py 3)
datav = np.random.random((1024, 1))
datai = np.random.random((1024, 1))
time = np.arange(0, 102.4, 0.1)
mdata = ma.MetaArray(np.array([datav, datai]),
info=[
{"name": "Signal", "cols": [
{"name": "Voltage", "units": "V"},
{"name": "Current", "units": "V"},
]
},
{"name": "Time", "units": "msec", "values": time},
{"name": "Trial"},
{"note": "Just some extra info"}
])
mdata.write('metaarray_py%d.ma'%sys.version_info[0]) # only write for the python version we are in
# regardless, read the file for the version we specified
fn = 'metaarray_py%s.ma' % version
print('Reading %s' % fn)
mdata = []
mdata = ma.MetaArray(file=fn)
f, ax = mpl.subplots(2, 1)
ax = ax.ravel()
ax[0].plot(mdata.xvals('Time'), mdata['Signal': 'Voltage'].view(np.ndarray), 'k')
ax[1].plot(mdata.xvals('Time'), mdata['Signal': 'Current'].view(np.ndarray), 'cyan')
mpl.show()