Bytes Command Function Not Working for PySerial - python

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'

Related

How to remove double quotes from list of strings?

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))

How to remove \n at the end of each value?

I want to make the input such that the user will type a separate number on each new line. I managed to put together this code
def str2arr(str):
arr = []
for line in str:
arr.append(str.replace('\n', ''))
return arr
import sys
a = sys.stdin.readlines()
print(a)
It is working nearly as I would like to, but the output looks like
['6543\n', '6543\n', '7654\n']
Is there a clever way to remove the \n?
And also, will I even get an usable integers using this method?
Thank you guys in advance.
You could use
a = ['6543\n', '6543\n', '7654\n']
integers = list(map(int, a))
print(integers)
# [6543, 6543, 7654]
Have a look at string.strip. That should provide the expected result.
You'll then have to call int() on each of the entries in the list.
Example:
>>> t = ['6543\n', '6543\n', '7654\n']
>>> [int(x.strip()) for x in t]
[6543, 6543, 7654]

print str and int without "( ' ," in Python with JSON

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

Separating parts of a <class 'byte'> and printing it out to screen

so I am capturing packets with Pydivert. I can print out the full packet payload by using
print(packet.tcp.payload)
OR
print(packet.payload)
output was
b'\x03\x00\x34\xe2\xd1' //continued like this
same output in both cases. I printed out the type by using
print(type(packet.payload))
This showed the type to be
<class 'byte'>
I would like to take say the first 10 byte positions from the output and type it out and also save it into a variable so when I'm modifying the payload, I exclude the initial bytes and then modify the remaining parts. So I can somehow attach the separated out bytes to my newly created bytes to create a final byte stream like for example:
TotalByteStream = (initial bytes which I separated out) + b'\x03\x00\x34\xe2\xd1\x78\x23\x45\x79' //continued like this as needed
//And then do
packet.payload = TotalByteStream
Is this possible?
I'm not sure I understand your question, but you can manipulate bytes in a manner similar to strings.
If you have your original payload:
>>> payload_1 = b'\x03\x00\xf4\xe2\xd1'
>>> type(payload_1)
<class 'bytes'>
>>> payload_1
b'\x03\x00\xf4\xe2\xd1'
You can slice of the first few bytes
>>> part = payload_1[:2]
>>> part
b'\x03\x00'
And later create a new payload where you prepend the part variable
>>> payload_2 = part + b'\xf5\xe5\xd5'
>>> payload_2
b'\x03\x00\xf5\xe5\xd5'
>>> payload_1
b'\x03\x00\xf4\xe2\xd1'
So you get a new payload with the same starting bytes. Does this answer your question? Or did I misunderstand your issue?

how to convert "b'\\xfe\\xff\\x002\\x000\\x001\\x009'" to character in python

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

Categories