I'd like to convert an array of integer values I have received over USB using pyusb to a list of hex values. I'd like these hex values to always have two bytes, i.e. 0x##. However the normal hex() function will return 0x1 with an input of 1. I'd like it to return 0x01.
Then after having the list of hex values I'd like to append them together while throwing away the '0x' portion. This is what I currently have, pretty simple.
data_read = dev.read(0x82,64,0,1000)
hex_data = range(0,len(data_read))
for i in range(0,len(data_read)):
hex_data[i] = hex(data_read[i])
Any ideas? I can fudge it and do it the sloppy way, but I was hoping there is a proper way to do it. Thank you.
Update:
data_read = dev.read(0x82,64)
print data_read
>>> array('B', [169, 86, 128, 1, 0, 128])
for i in range(0,len(data_read)):
hex_data[i] = hex(data_read[i])
print hex_data
>>> ['0xa9', '0x56', '0x80', '0x1', '0x0', '0x80']
The method suggested by Lavon did not work since the resulting hex values were technically strings in my code? Instead I just skipped my whole for loop converting to hex and directly did as Lavon and moooeeeep suggested and it worked! Thanks!
hex_data = ('%02x' %i for i in data_read)
print ''.join(hex_data)
>>> a95680010080
Is there a good reference you use for syntax? i.e. the '%02x' you used? I haven't seen that before and would like to understand it better.
Does this fit the bill?
data = [0x1, 0x4, 0x5, 0xFF, 0x12]
new_data = ['%02X' %i for i in data]
print ''.join(new_data)
yields:
010405FF12
using list comprehension and the join operation.
Alternatively, as suggested by #moooeeeep here is the solution using a generator:
new_data = ('%02X' %i for i in data)
print ''.join(new_data)
For the string formatting options, see this
Then after having the list of hex values I'd like to append them together while throwing away the '0x' portion.
Do you mean something like this:
In [8]: data_read = [0x01, 0x2b, 0x22, 0x10]
In [9]: ''.join(map(lambda v: '%02x' % v, data_read))
Out[9]: '012b2210'
?
Just another way to do it
>>> data_read = [0x01, 0x2b, 0x22, 0x10]
>>> ("{:02x}"*len(data_read)).format(*data_read)
'012b2210'
Related
I basically first converted a multidimensional array to a string array in order to set the values as my dictionary key, and now I need to convert the string array back to a regular float array. For example, what I have is:
str_array = ['[0.25 0.2916666666666667]', '[0.5833333333333334 0.2916666666666667]',
'[0.5555555555555555 0.3333333333333332]']
And I literally just need it back as a regular array
array = [[0.25 0.2916666666666667], [0.5833333333333334 0.2916666666666667],
[0.5555555555555555 0.3333333333333332]]
I have tried all the following : (*independently)
for i in str_arr:
i.strip("'")
np.array(i)
float(i)
Yet none of them work. They either cannot convert str --> float or they still keep the type as a str. Please help.
Use ast.literal_eval to convert str to another data type
import ast
str_array = ['[0.25 0.2916666666666667]', '[0.5833333333333334 0.2916666666666667]',
'[0.5555555555555555 0.3333333333333332]']
result = [ast.literal_eval(i.replace(" ", ",")) for i in str_array]
print(result) # [[0.25, 0.2916666666666667], [0.5833333333333334, 0.2916666666666667], [0.5555555555555555, 0.3333333333333332]]
You can also use the basic function eval.
[eval(x.replace(" ",",")) for x in str_array]
I have a function which takes a set of values and converts it into a bytes string. For example, I need:
input_array = ['E9', '01','06','57','4A','01','F4','01','01','EF']
## needs to become b'\xE9\x01\x06\x57\x4A\x01\xF4\x01\x01\xEF'
The function I have is:
def string_to_command(inp):
new_string = ''
for i in inp:
new_string += r'\x' + i
return new_string.encode('latin-1')
When I print both commands:
print(string_to_command(input_array))
print(b'\xE9\x01\x06\x57\x4A\x01\xF4\x01\x01\xEF')
# OUTPUT b'\\xE9\\x01\\x06\\x57\\x4A\\x01\\xF4\\x01\\x01\\xEF'
# OUTPUT b'\xe9\x01\x06WJ\x01\xf4\x01\x01\xef'
I am not sure what is going on here. The last one with b"" actually commands my output device properly, the other does not. How do I fix this problem?
You can convert to int first, then to bytes.
>>> a = ['E9', '01','06','57','4A','01','F4','01','01','EF']
>>> bytes(int(x, base=16) for x in a)
b'\xe9\x01\x06WJ\x01\xf4\x01\x01\xef'
The last one with b"" actually commands my output device properly, the other does not. How do I fix this problem?
I think what is going on here is that you are trying to add \x to every value and then encoding it from there. The problem with that is 'E9' and \x'E9' are not the same:
>>> 'E9'.encode()
b'E9'
>>> '\xE9'.encode()
b'\xc3\xa9' <-- Not the same
>>>
One method I like is bytes.fromhex(s), where s is your 'hex string'.
input_array = ['E9', '01','06','57','4A','01','F4','01','01','EF']
# use "".join(input_array) to get all values combined
# into one string
res = bytes.fromhex( "".join(input_array) )
Outputs :
b'\xe9\x01\x06WJ\x01\xf4\x01\x01\xef'
You can join a list of bytes converted from the original array with latin-1 encoding. So adding \x as join sequence, it will output the desired bytes object:
input_array = ['E9', '01','06','57','4A','01','F4','01','01','EF']
print(b''.join([bytes.fromhex(x) for x in input_array]))
Output:
b'\xe9\x01\x06WJ\x01\xf4\x01\x01\xef'
VERSION = ["'pilot-2'", "'pilot-1'"]
VERSIONS_F = []
for item in VERSION:
temp = item.replace('"','')
VERSIONS_F.append(temp)
print (VERSIONS_F)
In the above block of code VERSIONS_F is also printing the same ["'pilot-2'", "'pilot-1'"], but I would need something like ['pilot-2', 'pilot-1']. I even tried strip('"') and am not seeing what I want.
You can do this in a couple of lines:
VERSION = ["'pilot-2'", "'pilot-1'"]
VERSIONS_F = [item [1:-1] for item in VERSION]
print(VERSIONS_F)
OUTPUT:
['pilot-2', 'pilot-1']
This way simply slices the first and last character from the string, which assumes that the "" are always at the first and last position.
Note: Grismar gives a good overview of what is happening under the hood as well
Try this:
VERSION = ["'pilot-2'", "'pilot-1'"]
VERSIONS_F = []
for item in VERSION:
temp = item.replace("'",'')
VERSIONS_F.append(temp)
print (VERSIONS_F)
it will print ['pilot-2','pilot-1']
When you print a list, Python will print the representation of the list, so the strings inside of the list are not printed like a string normally is:
>>> print('hello')
hello
Compared to:
>>> print(['hello'])
['hello']
Adding different quotes will cause Python to select the opposite quotes to represent the string:
>>> print(['\'hello\''])
["'hello'"]
>>> print(["\"hello\""])
['"hello"']
Beginning Python programmers often make the mistake of confusing what is printed on the console with an actual value. print(x) doesn't show you the actual value of x (whatever that may be), but its text string representation.
For example:
>>> x = 0xFF
>>> print(x)
255
Here, a value is assigned as its hexadecimal representation, but of course the actual value is just 255 (in decimal representation) and the decimal representation is the standard representation chosen when printing an integer value.
The 'real' value of the variable is an abstract numerical value, choices made when representing it don't affect that.
In your case, you defined the strings as having single quotes as part of the string using VERSION = ["'pilot-2'", "'pilot-1'"]. So, if you want to remove those single quotes, you could:
VERSION = ["'pilot-2'", "'pilot-1'"]
VERSIONS_F = []
for item in VERSION:
temp = item.replace("'",'')
VERSIONS_F.append(temp)
print (VERSIONS_F)
Result:
['pilot-2']
['pilot-2', 'pilot-1']
Or, more simply:
VERSIONS_F = [v.strip("'") for v in VERSION]
In response to the comment:
VERSION = ["'pilot-2'", "'pilot-1'"]
temp_list = ['pilot-1', 'test-3']
print(any(x in [v.strip("'") for v in VERSION] for x in temp_list))
I am currently working with JSON and Python and I have a problem.
When I write:
x = {}
x['red'] = {'name': "red"}
y = {}
y['red'] = {'p': 1}
z = x['red']['name'], y['red']['p']
print(z)
I get back:
('red', 1)
But I want it like:
red1
Without using
print(x['red']['name'], y['red']['p'])
Thanks for your help :)
When we resolve the variables in the line
z = x['red']['name'], y['red']['p']
we get this:
z = "red", 1
This is, in Python the same as writing:
z = ("red", 1)
This line defines a data-type called a "tuple". It is similar to a list. When you use print to write out the value of this variable, Python formats this as such and adds the parens.
If you want the string "red1" as output, you need to do some minor string processing. In your tuple, your first item is a string, the next is an integer. Those two are not directly concatenable in Python using +. You either need to convert (cast) the number first, or use a string formatting function:
Example 1 - Using str() to cast the number to string
z = x['red']['name'] + str(y['red']['p'])
Example 2 - Using simple string formatting
z = '%s%s' % (x['red']['name'], y['red']['p'])
Example 3 - Using f-strings
z = f"{x['red']['name']}{y['red']['p']}"
Just concatenate the string, easy:
z = y['red']['name'] + str(z['red']['p'])
print(z)
You need to call str() around z['red']['p'] because it's an integer. By converting it to a string, you can then concatenate the two strings into one string
When you type z = x['red']['name'], y['red']['p'] Python automatically takes it as tuple.
But you want this to be treated as string and get concatenated results.
for this you may use,
z = str(x['red']['name']) + str(y['red']['p'])
print(''.join(z)) does the trick.
Cheers
Demo: https://repl.it/repls/MinorRoyalTrace
Edit: use print(''.join(str(element) for element in z)) instead for handle str+ int
I have a program, which is returning strings like : b'\\xfe\\xff\\x000\\x008\\x00/\\x001\\x002\\x00/\\x001\\x009\\x009\\x003'
How can I convert this to a readable string. The value of this should be 08/12/1993
so imagine i have something like this
a = "b'\\xfe\\xff\\x000\\x008\\x00/\\x001\\x002\\x00/\\x001\\x009\\x009\\x003'"
print(a.convert())
The sequence \xfe\xff tells us we are having utf-16 (cf. http://unicodebook.readthedocs.io/guess_encoding.html)
Let us try:
x = b'\xfe\xff\x000\x008\x00/\x001\x002\x00/\x001\x009\x009\x003'
print(x.decode('utf-16'))
which gives
'08/12/1993'
For completeness:
If the input is given as a string you can use eval to turn it into <class 'bytes'>:
x = eval("b'\\xfe\\xff\\x000\\x008\\x00/\\x001\\x002\\x00/\\x001\\x009\\x009\\x003'")
print(x) ### b'\xfe\xff\x000\x008\x00/\x001\x002\x00/\x001\x009\x009\x003'
print(x.decode('utf-16')) ### returns 08/12/1993