I am encountering an error in outputting a formatted string. I am using Python2.6
lat = 23.456
long = 34.129
# I want to output lat and long, both occupying 8 columns in width, right justified and with 2 values beyond the decimal point
site_file = open('test.site','w')
site_file.write('[{:8.2f}{:8.2f}]'.format(lat,long))
I get the following error:
ValueError: zero length field name in format
Any ideas on what I am doing wrong?
thanks!
Python 2.6 and earlier require that you specify the index of the formatted values. Here is an example:
'[{} {}]'.format(a, b) # Python 2.7 and later
'[{0} {1}]'.format(a, b) # Python 2.6 and earlier
I do not have a Python 2.6 interpreter handy, but I believe this is the syntax that you need:
site_file.write('[{0:8.2f}{1:8.2f}]'.format(lat,long))
Related
I have some code that I have been running in Python 3.6, but when I move to Python 3.9 I recieve the below error:
SyntaxError: can't use starred expression here
I understand some syntax related to expressions of the form (*something) was implemented in 3.9 that is not backwards compatible (see, for example, here).
Here is a minimal working example of what my code tries to do:
# Get some data
y = np.random.randn(100,100,100)
# Indexes stored as a tuple
x = (1,2)
# Result I'm after
result = y[...,(*x)]
In the above example, I am trying to essentially return y[:,1,2], but in practice, my tuple may have more values, and my array may be larger.
The above code works fine in Python 3.6 but doesn't work in Python 3.9. I cannot work out what the equivalent piece of code would be in Python 3.9 and above. I don't want to assume the number of dimensions in Y (e.g. I want to keep the ...), but I want to retain the behaviour I have above. How can I do this?
You were almost there:
result = y[(..., *x)]
Intermediate:
(..., *x)
# (Ellipsis, 1, 2)
I am attempting to decode some data from a Shark 100 Power Meter via TCP modbus. I have successfully pulled down the registers that I need, and am left with two raw values from the registers like so:
[17138, 59381]
From the manual, I know that I need to convert these two numbers into a 32bit IEEE floating-point number. I also know from the manual that "The lower-addressed register is the
high order half (i.e., contains the exponent)." The first number in the list shown above is the lower-addressed register.
Using Python (any library will do if needed), how would I take these two values and make them into a 32 bit IEEE floating point value.
I have tried to use various online converters and calculators to figure out a non-programmatic way to do this, however, anything I have tried gets me a result that is way out of bounds (I am reading volts in this case so the end result should be around 120-122 from the supplied values above).
Update for Python 3.6+ (f-strings).
I am not sure why the fill in #B.Go's answer was only 2. Also, since the byte order was big-endian, I hardcoded it as such.
import struct
a = 17138
b = 59381
struct.unpack('>f', bytes.fromhex(f"{a:0>4x}" + f"{b:0>4x}"))[0]
Output: 121.45304107666016
The following code works:
import struct
a=17138
b=59381
struct.unpack('!f', bytes.fromhex('{0:02x}'.format(a) + '{0:02x}'.format(b)))
It gives
(121.45304107666016,)
Adapted from Convert hex to float and Integer to Hexadecimal Conversion in Python
I read in the comments, and #Sanju had posted this link: https://github.com/riptideio/pymodbus/blob/master/examples/common/modbus_payload.py
For anyone using pymodbus, the BinaryPayloadDecoder is useful as it's built in. It's very easy to pass a result.registers, as shown in the example. Also, it has a logging integrated, so you can help debug why a conversion isn't working (ex: wrong endianness).
As such, I made a working example for this question (using pymodbus==2.3.0):
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
a = 17138
b = 59381
registers = [a, b]
decoder = BinaryPayloadDecoder.fromRegisters(registers, byteorder=Endian.Big)
decoder.decode_32bit_float() # type: float
Output: 121.45304107666016
Attempting to use script that was built in Python 2, and now use it in Python 3 without adding a version 2 onto system. For the script, the only error I get is related to a struct.unpack at this line....
def go_parse(rec_list):
size = (len(rec_list) - 4) / 4
first_arg = "%sI" % size
return struct.unpack(first_arg, (rec_list.rstrip ('\xff\xff\xff\xff')))
at line 4 of this function, I get the error:
TypeError: a bytes-like object is required, not 'str'
I read several other posts regarding this, and that it needs to be explicitly labeled as bytes, but I cant seem to figure out where to explicitly label that in this context. The other examples on SO i found here and here, did not provide much of an explanation to it. The struct pages don't seem to cover the error possibilities of 2-3...Only that struct.unpack(fmt, buffer) has the two arguments of fmt and buffer. Based on those examples, i have tried identifying this as bytes explicitly as a second arg using b, as well as bytes before the arguments and on the tuple for the .strip. I attempted return this as a bytearray, but that seemed to produce the same errors.
As an alternative, I am able to get the byte data I wanted into a list as shown below, what would be a way to get the list into unpack, attempt b'i' just looks at i as bytes.
list1 = [b'\x03\x00\x00\x00\xff\xff\xff\xff',
b'\x07\x00\x00\x00\x06\x00\x00\x00\xff\xff\xff\xff']
print(struct.unpack('<s', bytes(i)))
The bytes are of varying length, but all end in \xff\xff\xff\xff. The data I am looking at is text, just trying to bring it back to text.
I answered my own question spending some time in the Documentation, and someone pointing me in the right direction.
Generating a list of binary data that needed to be brought back to text for display, I used the codecs, a standard library. All my binary data was saved into a list named bin_list.
import codecs
bin_list = [b'Some Binary data', b'some more binary data']
for i in bin_list: # used the loop to print each to new line, nice and neat
print (codecs.decode(i, "utf-8", "ignore")) # or any other conversion avilable on codecs.
# Formats a color
def formatColor(self, color):
return "#%.2x%.2x%.2x" % (color.r*255, color.g*255, color.b*255)
This method is a part of Blender addon for exporting model to xaml. When I try to run conversion Blender returns an which says "%x format an integer is required not float". I thought that .2 is a problem here so tried to modify formatter like this
"#%0x%0x%0x"
but error persists. Blender uses python 3.5 so I tried to replace it with 3.4 and it doesn't help either. With python 2.7 latest Blender does not even starts.
I also tried this
int(color.r*255)
and this
int(round(color.r))*255
but an error is always the same.
How could I modify this method such that it returns an integer not float?
In case anybody will use this plugin. After casting in such a way conversion to xaml works fine for python 3.5.
"#%.2x%.2x%.2x" % (int(color.r*255), int(color.g*255), int(color.b*255))
2nd Edit
This is how a "stokes_line" is generated:
os.system('pdv -t %s > temp.txt ' % epoch_name)
stokes_line = np.genfromtxt('temp.txt', usecols=3, dtype=[('stokesI','float')], skip_header=1)
os.system('vap -nc "mjd" %s >> mjd.txt' % new_y[i])
stokes_list[b] = stokes_line
"pdv" is a command from another programme which generated some numbers used in the "stokes_line".
stokes_list just gets a new stokes_line added too each in a loop each time.
EDIT:
A stokes_line is created with a numpy.genfromtxt command (and so extracts from a txt file) and is made up of floats and they look like this:
[(0.00126596,) (0.000621272,) (0.00058694,) ..., (0.0015368,)
(0.000926448,) (7.95851e-05,)]
A bunch of them together make up a stokes_list, and each stokes_line is made up of the same number of floats.
Is the problem because the genfromtxt is not creating a list which would be all square brackets, but something else (is it called a sequence)??
I wrote a python code which worked find on my laptop (python version 2.7.3), but it doesn't seem to run on my university desktop (python version 2.5.2).
I don't think that showing lots of the code here will be useful, but the error message is on the second of these two lines:
os.system('vap -nc "mjd" %s >> mjd.txt' % new_y[i])
stokes_list[b] = stokes_line
Where "vap" is a command from another programme which returns some values. Anyway, the crux of the matter is that I get the following error message ONLY when I run on the older version of Python:
ValueError: setting an array element with a sequence.
Now I did a little research, and people say that the problem is due to incompatible lengths of lists of some such - but if that was the case, why does it work fine when I run it on my newer version of Python.
Any help would be great, thank you!
.format, the Formatter class was added in 2.6.
os.system('vap -nc "mjd" %s >> mjd.txt' % new_y[i]) should work.
When you're using np.genfromtxt(…, usecols=3, dtype=[("stokesI","float")]), you're constructing a structured array with only one field ("stokesI"). Of course, when you print the array, this structure appears:
[(0.00126596,) (0.000621272,) (0.00058694,) ..., (0.0015368,) (0.000926448,) (7.95851e-05,)]
Each item is a np.void consisting of a named float field.
Looks a bit wasteful, you could probably simplify your expression as :
np.genfromtxt(…,usecols=3, dtype=float)
You then get:
[ 1.26596000e-03 6.21272000e-04 5.86940000e-04 ... 1.53680000e-03
9.26448000e-04 7.95851000e-05]
The probable reason why it apparently fails on an older version of Python is that you're using an older version of NumPy, like 1.4 or 1.5. There have been some improvements on the construction of ndarrays since (better handling of generators, automatic conversion from strings…)