I'm trying to convert an old python2 code to python3, and I'm facing a problem with strings vs bytes
In the old code, this line was executed:
'0x' + binascii.hexlify(bytes_reg1)
In python2 binascii.hexlify(bytes_reg1) was returning a string but in python3 it returns bytes, so it cannot be concatenated to "0x"
TypeError: can only concatenate str (not "bytes") to str
I tried converting it to string:
'0x' + str(binascii.hexlify(bytes_reg1))
But what I get as a result is:
"0xb'23'"
And it should be:
"0x23"
How can I convert the bytes to just 23 instead of b'23' so when concatenating '0x' I get the correct string?
can you try doing this and let me know whether it worked for you or not :
'0x' + str(binascii.hexlify(bytes_reg1)).decode("utf-8")
# or
'0x' + str(binascii.hexlify(bytes_reg1), encoding="utf-8")
note- Also if you can provide the sample of bytes_reg1, it will be easier to provide a solution.
Decode is the way forward, as #Satya says.
You can access the hex string in another way:
>>> import binascii
>>> import struct
>>>
>>> some_bytes = struct.pack(">H", 12345)
>>>
>>> h = binascii.hexlify(some_bytes)
>>> print(h)
b'3039'
>>>
>>> a = h.decode('ascii')
>>> print(a)
3039
>>>
>>> as_hex = hex(int(a, 16))
>>> print(as_hex)
0x3039
>>>
Related
I am working on going from o-string binary to Unicode, part of this process requires converting Raised Position to Binary. I can't seem to be able to get it done. The doc test will explain what needs to be performed.
I have provided my code below but it is nowhere close to getting the correct answer.
def raisedpos_to_binary(s):
''' (str) -> str
Convert a string representing a braille character in raised-position
representation into the binary representation.
TODO: For students to complete.
>>> raisedpos_to_binary('')
'00000000'
>>> raisedpos_to_binary('142536')
'11111100'
>>> raisedpos_to_binary('14253678')
'11111111'
>>> raisedpos_to_binary('123')
'11100000'
>>> raisedpos_to_binary('125')
'11001000'
'''
res = ''
lowest_value = '00000000'
for i, c in enumerate(s):
if c == i:
lowest_value = lowest_value.replace('0', '1')
return lowest_value
Looks like you can create a set (converted to integers) of the single digits and then produce '1' or '0' iterating over a range of 1..8, eg:
def raisedpos_to_binary(digits):
raised = {int(digit) for digit in digits}
return ''.join('1' if n in raised else '0' for n in range(1, 9))
Tests:
for test in ['', '142536', '14253678', '123', '125']:
print(test, '->', raised_pos_to_binary(test))
Gives you:
-> 00000000
142536 -> 11111100
14253678 -> 11111111
123 -> 11100000
125 -> 11001000
So in full, your module should contain:
def raisedpos_to_binary(digits):
"""
>>> raisedpos_to_binary('')
'00000000'
>>> raisedpos_to_binary('142536')
'11111100'
>>> raisedpos_to_binary('14253678')
'11111111'
>>> raisedpos_to_binary('123')
'11100000'
>>> raisedpos_to_binary('125')
'11001000'
"""
raised = {int(digit) for digit in digits}
return ''.join('1' if n in raised else '0' for n in range(1, 9))
if __name__ == '__main__':
import doctest
doctest.testmod()
Then run your script using:
python your_script.py -v
I want to take the first line of a file opened from an url, search for a specific string and then split that string.
request=urllib.request.Request(url)
response=urllib.request.urlopen(request)
input_file=response.readlines()
for l in input_file:
if "target" in l:
dum, stat = l.split(":")
stat = stat.strip()
I expect to get a stat="StationX"
instead I get
TypeError: a bytes-like object is required, not 'str'
because input_file is a list of type bytes instead of type strings.
I don't know how to either bring input_file in as strings (I thought thats what readlines() vs read() did?) or convert the list of type bytes to a list of type stings.
The urllib.request package has a little nuance to it as highlighted below. One might expected the return type of .read() to be a string but it's actually raw bytes that you have to decode.
>>> import urllib.request
>>> req = urllib.request.Request("http://www.voidspace.org.uk")
>>> res = urllib.request.urlopen(req)
>>> raw_contents = res.read()
>>> type(raw_contents)
<class 'bytes'>
>>> page = raw_contents.decode()
>>> type(page)
<class 'str'>
Now in your case
request = urllib.request.Request(url)
response = urllib.request.urlopen(request)
raw_lines = response.readlines()
for raw_line raw_lines:
line = raw_line.decode()
if "target" in line:
dum, stat = l.split(":")
stat = stat.strip()
Alternatively,
for line in map(lambda x: x.decode(), raw_lines):
# etc
I am trying to read a binary file and get out a header which is in utf-8 format. However the rest of the file has byte values that go over decimal 127, so I cannot convert that to a string. I have to split the text until ; (or 0x3B) and I cannot get it to work.
with open("test_qifs_single_frame.qifs", "rb") as file:
data = file.read()
print(binascii.hexlify(data))
I cannot read it in as a string either, because it tells me that I cannot decode 0x81 to UTF-8. Which I understand, it falls outside of the ASCII range. What can I do to solve this?
You can read the file byte by byte until you reach the stop character, then decode the data that you have read.
Create some sample data
>>> from random import randint
>>> header = 'Heaðer;'.encode('utf-8')
>>> bs = b''.join(bytes.fromhex('{:0>2x}'.format(randint(0, 255))) for _ in range(56))
>>> with open('test_qifs_single_frame.qifs', 'wb') as f:
... f.write(header + bs)
>>>
Read the header from the file
>>> # Create a bytearray to hold the bytes that we read.
>>> ba = bytearray()
>>> import functools
>>> with open('test_qifs_single_frame.qifs', 'rb') as f:
... breader = functools.partial(f.read, 1)
... for b in iter(breader, b';'):
... ba += b
...
>>> ba
bytearray(b'Hea\xc3\xb0er')
>>> ba.decode('utf-8')
'Heaðer'
If the iter builtin is passed a callable and a value, it will call the callable until it returns the value. In the code we use functools.partial to create a function that reads the file one byte at a time, then pass this to iter.
How to print ♠ at terminal where I read string u"\u2660" from data.txt
data = "./data.txt"
with open(data, 'r') as source:
for info in source: print(info)
u"\u2660" is what I get in the terminal
The string u"\u2660" is just a plain text in a txt file. It needs to be interpreted by python interpreter to become a string which represents the unicode character. And you can use eval to do that.
>>> a=r'u"\u2660"'
>>> print(a)
u"\u2660"
>>> b = eval(a)
>>> print(b)
♠
Consider:
>>> a = '\xe3'
>>> a
'ã'
>>> a.encode('cp1252')
b'\xe3'
I would like to recreate the a variable if the user input the string e3:
>>> from_user = 'e3'
>>> a = '\x' + from_user
File "<stdin>", line 1
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 0-1: end of string in escape sequence
>>> a = '\\x' + from_user
>>> a
'\\xe3'
>>> a.encode('cp1252')
b'\\xe3'
With the string from_user, how might I create the a variable such that I could use it just like I did in the first example?
This should give you an idea:
unichr(int('e3', 16)).encode('cp1252')