I read UART port with this:
print ("Attempt to Read")
readOut = serial_port.readline()
time.sleep(1)
in_hex = hex(int.from_bytes(readOut,byteorder='big'))
print ("Reading: ", in_hex)
and then it gives me output e.g. like:
Attempt to Read
Reading: 0x6011401011403
So there is one leading zero missing before number 6. I can't find a way to add it without specifying in the code the length of the whole string (and I don't want to do that, becasue the string can have variable length e.g. like 0x056822). Could you please help?
You could inject a zero after 0x when the number of characters is odd:
if len(in_hex)%2: in_hex = in_hex.replace("0x","0x0")
Even number of digits is guaranteed if you convert each byte to two characters:
hexstr = ''.join(format(b,'02x') for b in bytesequence)
Just prepend "0x" if you want.
Related
I got an strange error I have never seen before and I tried to find some information over the web but without sucess.
I try to do a simple thing, converting an str to flaot. When I print the value it is in classic number style (37 442.20) but when I want to convert it to flaot I get an Error showing the value in a mix of number and letter (37\u202f442.20). With the following lines I get :
print(value)
print(type(value))
37 442.20
<class 'str'>
print(float(value))
ValueError: could not convert string to float: '37\u202f442.20'
Someone know what's going wrong here ?
s = "37 442.20"
print (float(s.replace(' ','').encode('ascii', 'ignore')))
Output:
37442.2
You have both the space and encoding problems.
So you use replace() method on your string and encode() to pass through each and print your float.
In order to avoid error upon conversion of a list of mixed non digit string and digit strings, and considering your encoding problem, you can do:
import re
sl = ["37 442.20","aaa.83","4a3.","aaaa","345"]
for s in sl:
s = s.replace(' ','').encode('ascii', 'ignore')
if re.match(b"^([0-9]+){0,1}[.]{0,1}([0-9]+)$",s):
print (float(s))
else:
print ("%s not digit" % s.decode())
Output:
37442.2
aaa.83 not digit
4a3. not digit
aaaa not digit
345.0
It’s simply because you have white space between digits. Remove the white space and pass the value to float and it should work fine.
One way to do this:
value = “”.join(‘37 442.20’.split())
print(float(value))
The \u202f character is not a normal space.
https://www.fileformat.info/info/unicode/char/202f/index.htm
You can try remove them first before converting. For example:
u'37\u202f442.20'.encode('ascii', 'ignore')
Can anyone please explain this block of code to me? I don't really understand.
Why do I need to declare uniMessage = "" what is the use of it here? Sometimes when I code I realise that I need to declare it beforehand but sometimes I don't need to.
Why I need to use += and also convert the user inputted word into str? Isn't += is like unicode = unicode + str(ord(char))? I don't see the impact of += here why can't I just use =. And if I thought that the user inputted message is already a string? Why do I need to convert it into str again?
Also it is not necessary to convert convMessage += chr(int(alphabet)) into integer isn't it?
message = input("Enter a word ")
uniMessage = ""
for char in message:
uniMessage += str(ord(char))
print("Unicode message:", uniMessage)
convMessage = ""
for i in range(0, len(uniMessage)-1, 2):
alphabet = uniMessage[i] + uniMessage[i+1]
convMessage += chr(int(alphabet))
print("Orginal message:", convMessage)
Important clarification
The code is not a real Unicode encoding/decoding because is supposing that the Unicode characters you will input have just two decimal digits. You can test that yourself if you enter def as input, those characters have 100, 101 and 102 ASCII code.
(1)uniMessage = "" needed because you are using it the first time as a right part of an assignment operator.
uniMessage += str(ord(char))
is "equivalent" to:
uniMessage = uniMessage + str(ord(char))
and in Python a variable need to be declared before used and the = operator evaluate the right operant first.
(2) += is just syntax sugar, so yes, you can use the =, but some people would say that is less pythonic and "harder" to read ;) I recommend to use += when you can. You have to convert to string using str because you are before converting user input to a number using ord. ord
(3) Is necessary because uniMessage is a string, a string full of digits characters, but still a string.
That code might intend to convert characters into their internal number representation and back to a string. But that code just fails for 8-bit coded characters below line feed (typically 0x0A = 10dec) and above "c" (0x63 = 99dec).
Besides that, in Python every string is a Unicode string with a UTF-8 encoding. Using other encoding is possible (str.encode()), however, will yield "bytes"
I have a list of strings that look something like this:
"['id', 'thing: 1\nother: 2\n']"
"['notid', 'thing: 1\nother: 2\n']"
I would now like to read the value of 'other' out of each of them.
I did this by counting the number at a certain position but since the position of such varies I wondererd if I could read from a certain character like a comma and say: read x_position character from comma. How would I do that?
Assuming that "other: " is always present in your strings, you can use it as a separator and split by it:
s = 'thing: 1\nother: 2'
_,number = s.split('other: ')
number
#'2'
(Use int(number) to convert the number-like string to an actual number.) If you are not sure if "other: " is present, enclose the above code in try-except statement.
I wrote a program that turns a text into ASCII numbers, and then it turns the ASCII numbers back into the original text. Right now it works with both lowercase letters and uppercase letters but it doesn't work with spaces. This is how my code looks right now:
message_hidden = input("Enter a message that will be hidden: ")
hidden = ""
norm_message = ""
for i in message_hidden:
hidden = hidden + str(ord(i)-23)
print(hidden)
for i in range(0, len(hidden), 2):
code = hidden[i] + hidden[i+1]
norm_message = norm_message + (chr(int(code)+23))
print("The first message was: ", norm_message)
My first attempt was to rewrite the first loop like this:
for i in message_hidden:
if i.isalpha():
hidden = hidden + str(ord(i)-23)
else:
hidden = hidden + i
print(hidden)
And from here I don't know how I should write the second loop to make it work. Can anyone give me some suggestions about how I should go from here?
ord(' ') == 32 and 32-23 == 9, which is single digit. You are assuming that your numerical codes are all 2 digits. If you want to keep that assumption, you need to find a different way to encrypt the space character. To do this find a 2-digit number that isn't one of the numbers obtained by a-zA-Z. Using an explicit if -- encrypt the space character to this number. When decrypting, you will also need to use an explicit if to handle this case.
Alternatively, find a different function (other that subtracting by 23), which you apply to ord(letter) -- one which gives 2 digit numbers for all ord() values that you are interested in. There are infinitely many functions which satisfy this property. Whether or not you can find one which would require less code than simply putting a band aid on the space character is another question.
I am currently trying to find a way to convert any sort of text to a number, so that it can later be converted back to text.
So something like this:
text = "some string"
number = somefunction(text)
text = someotherfunction(number)
print(text) #output "some string"
If you're using Python 3, it's pretty easy. First, convert the str to bytes in a chosen encoding (utf-8 is usually appropriate), then use int.from_bytes to convert to an int:
number = int.from_bytes(mystring.encode('utf-8'), 'little')
Converting back is slightly trickier (and will lose trailing NUL bytes unless you've stored how long the resulting string should be somewhere else; if you switch to 'big' endianness, you lose leading NUL bytes instead of trailing):
recoveredstring = number.to_bytes((number.bit_length() + 7) // 8, 'little').decode('utf-8')
You can do something similar in Python 2, but it's less efficient/direct:
import binascii
number = int(binascii.hexlify(mystring.encode('utf-8')), 16)
hx = '%x' % number
hx = hx.zfill(len(hx) + (len(hx) & 1)) # Make even length hex nibbles
recoveredstring = binascii.unhexlify(hx).decode('utf-8')
That's equivalent to the 'big' endian approach in Python 3; reversing the intermediate bytes as you go in each direction would get the 'little' effect.
You can use the ASCII values to do this:
ASCII to int:
ord('a') # = 97
Back to a string:
str(unichr(97)) # = 'a'
From there you could iterate over the string one character at a time and store these in another string. Assuming you are using standard ASCII characters, you would need to zero pad the numbers (because some are two digits and some three) like so:
s = 'My string'
number_string = ''
for c in s:
number_string += str(ord(c)).zfill(3)
To decode this, you will read the new string three characters at a time and decode them into a new string.
This assumes a few things:
all characters can be represented by ASCII (you could use Unicode code points if not)
you are storing the numeric value as a string, not as an actual int type (not a big deal in Python—saves you from having to deal with maximum values for int on different systems)
you absolutely must have a numeric value, i.e. some kind of hexadecimal representation (which could be converted into an int) and cryptographic algorithms won't work
we're not talking about GB+ of text that needs to be converted in this manner