How to properly use binascii.crc32 on a byte array - python

I have what should be an array of Hex but always seen as a 'str' by binascii.crc32().
As an exemple : data = ['aa', 'bb', 'cc'].
This is for frame building in order to put it in a txt file openable by Wireshark under specific format (not the problem here, this works fine).
As shown in documentation :
print(binascii.crc32(b"hello world")) works.
I tried to convert data into binary with bin() which gave me
data = ['10101010', '10111011', '11001100']
However it is never seen as binary.
I tried to convert it using bytes() method but only managed to convert it into ASCII again.
def toBin(data):
data2=[]
for iBcl in range (1,len(data)):
if iBcl%2!=0:
binary=bin(int(data[iBcl-1]+data[iBcl],16))[2:]
data2.append(binary)
print(data2)
return data2
data="aabbcc"
data2=toBin(data)
print(binascii.crc32(data2[0]+data2[1]+data2[2]))
According to online CRC32 calculator the result should be
0xBE4DF84C but i've got the following error :
TypeError: a bytes-like object is required, not 'str'
I don't get the error using bytes() method but CRC32 is then calculated on ASCII character and this give me incorrect crc.

You have a list of hexadecimal data. You can convert each byte with binascii.unhexlify and then join all:
b = b''.join((binascii.unhexlify(i) for i in data))
print(b)
gives as expected
b'\xaa\xbb\xcc'
You can control the crc32:
print(hex(binascii.crc32(b)))
which gives:
0xbe4df84c

Related

How to convert a string array to float array?

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]

Bytes Command Function Not Working for PySerial

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'

How do I change the CSV data to a float?

I have a piece of code that is meant to read a CSV file that has data in it. I get this error message when I run the program, "ValueError: could not convert string to float:" How can I make my strings into floats?
,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r = np.loadtxt('car.txt', delimiter = '\s', unpack = True)
plt.plot(o,r, label='Loaded from file!')
plt.xlabel('o')
plt.ylabel('r')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
ValueError: could not convert string to float:
Python use float() function to convert a string into a float. The ValueError happens when Python doesn't know how to do so
for example
float("1.234") # return 1.234
float("1.45 ") # return 1.45
but if you do
float("abc")
This will cause a ValueErrror since Python doesn't know how to convert it.
Back to your question, maybe try to print your variable and check if it is valid to be converted to float.
if all your data are float, maybe:
1,the first rou are names not float
2,maybe there are 'backspace' in your data, they will be recognize as '/t', find a spack in your data,press ctrl+r,change backspace to space

Append string to a numpy ndarray

I'm working with a numpy array called "C_ClfGtLabels" in which 374 artist/creator names are stored. I want to append a 375th artist class with a string "other artists". I thought I could just do that as follows:
C_ClfGtLabels.append('other artists')
However, this results in the following error:
AttributeError: 'numpy.ndarray' object has no attribute 'append'
I saw found this problem a few times on stackoverflow, to which the answer in one case was to use concatenate instead of append. When I tried that I got the following error:
TypeError: don't know how to convert scalar number to int
It seems to be a problem that the datatype does not match the datatype that I, trying to append/concatenate, which would be of type string. However, I don't know what I should do to make them match. The data inside the Clabels array is as follows:
[u"admiral, jan l'" u'aldegrever, heinrich' u'allard, abraham'
u'allard, carel' u'almeloveen, jan van' u'altdorfer, albrecht'
u'andriessen, jurriaan' u'anthonisz., cornelis' u'asser, eduard isaac' ..]
Any advice on how I can setup the "other artists" string so that I can append it to C_ClfGtLabels?
A quick workaround is to convert your C_ClfGtLabels into a list first, append, and convert it back into an ndarray
lst = list(C_ClfGtLabels)
lst.append('other artists')
C_ClfGtLabels = np.asarray(lst)

Why am I seeing "TypeError: string indices must be integers"?

I'm playing with both learning Python and am trying to get GitHub issues into a readable form. Using the advice on How can I convert JSON to CSV?, I came up with this:
import json
import csv
f = open('issues.json')
data = json.load(f)
f.close()
f = open("issues.csv", "wb+")
csv_file = csv.writer(f)
csv_file.writerow(["gravatar_id", "position", "number", "votes", "created_at", "comments", "body", "title", "updated_at", "html_url", "user", "labels", "state"])
for item in data:
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])
Where "issues.json" is the JSON file containing my GitHub issues. When I try to run that, I get
File "foo.py", line 14, in <module>
csv_file.writerow([item["gravatar_id"], item["position"], item["number"], item["votes"], item["created_at"], item["comments"], item["body"], item["title"], item["updated_at"], item["html_url"], item["user"], item["labels"], item["state"]])
TypeError: string indices must be integers
What am I missing here? Which are the "string indices"? I'm sure that once I get this working I'll have more issues, but for now, I'd just love for this to work!
When I tweak the for statement to simply
for item in data:
print item
what I get is ... "issues" -- so I'm doing something more basic wrong. Here's a bit of my JSON content:
{"issues": [{"gravatar_id": "44230311a3dcd684b6c5f81bf2ec9f60", "position": 2.0, "number": 263, "votes": 0, "created_at": "2010/09/17 16:06:50 -0700", "comments": 11, "body": "Add missing paging (Older>>) links...
when I print data, it looks like it is getting munged really oddly:
{u'issues': [{u'body': u'Add missing paging (Older>>) lin...
The variable item is a string. An index looks like this:
>>> mystring = 'helloworld'
>>> print mystring[0]
'h'
The above example uses the 0 index of the string to refer to the first character.
Strings can't have string indices (like dictionaries can). So this won't work:
>>> mystring = 'helloworld'
>>> print mystring['stringindex']
TypeError: string indices must be integers
item is most likely a string in your code; the string indices are the ones in the square brackets, e.g., gravatar_id. So I'd first check your data variable to see what you received there; I guess that data is a list of strings (or at least a list containing at least one string) while it should be a list of dictionaries.
TypeError for Slice Notation str[a:b]
Short Answer
Use a colon : instead of a comma , in between the two indices a and b in str[a:b]:
my_string[0,5] # wrong ❌
my_string[0:5] # correct ✅
Long Answer
When working with strings and slice notation (a common sequence operation), it can happen that a TypeError is raised, pointing out that the indices must be integers, even if they obviously are.
Example
>>> my_string = "Hello, World!"
>>> my_string[0,5]
TypeError: string indices must be integers
We obviously passed two integers for the indices to the slice notation, right? So what is the problem here?
This error can be very frustrating - especially at the beginning of learning Python - because the error message is a little bit misleading.
Explanation
We implicitly passed a tuple of two integers to the slice notation when we called my_string[0,5]. 0,5 evaluates to the same tuple as (0,5) does - even without the parentheses. Why though?
A trailing comma , is actually enough for the Python interpreter to evaluate something as a tuple:
>>> my_variable = 0,
>>> type(my_variable)
<class 'tuple'>
So what we did there, this time explicitly:
>>> my_string = "Hello, World!"
>>> my_tuple = 0, 5
>>> my_string[my_tuple]
TypeError: string indices must be integers
Now, at least, the error message makes sense.
Solution
We need to replace the comma , with a colon : to separate the two integers correctly, not having them interpreted as a tuple:
>>> my_string = "Hello, World!"
>>> my_string[0:5]
'hello'
A clearer and more helpful error message could have been something like:
TypeError: string indices must be integers not tuple
^^^^^
(actual type here)
A good error message should show the user directly what they did wrong! With this kind of information it would have been much more easier to find the root cause and solve the problem - and you wouldn't have had to come here.
So next time, when you find yourself responsible for writing error description messages, remind yourself of this example and add the reason (or other useful information) to error message! Help other people (or maybe even your future self) to understand what went wrong.
Lessons learned
slice notation uses colons : to separate its indices (and step range, i.e., str[from:to:step])
tuples are defined by commas , (i.e., t = 1,)
add some information to error messages for users to understand what went wrong
data is a dict object. So, iterate over it like this:
Python 2
for key, value in data.iteritems():
print key, value
Python 3
for key, value in data.items():
print(key, value)
I had a similar issue with Pandas, you need to use the iterrows() function to iterate through a Pandas dataset Pandas documentation for iterrows
data = pd.read_csv('foo.csv')
for index,item in data.iterrows():
print('{} {}'.format(item["gravatar_id"], item["position"]))
note that you need to handle the index in the dataset that is also returned by the function.
As a rule of thumb, when I receive this error in Python I compare the function signature with the function execution.
For example:
def print_files(file_list, parent_id):
for file in file_list:
print(title: %s, id: %s' % (file['title'], file['id']
So if I'll call this function with parameters placed in the wrong order and pass the list as the 2nd argument and a string as the 1st argument:
print_files(parent_id, list_of_files) # <----- Accidentally switching arguments location
The function will try to iterate over the parent_id string instead of file_list and it will expect to see the index as an integer pointing to the specific character in string and not an index which is a string (title or id).
This will lead to the TypeError: string indices must be integers error.
Due to its dynamic nature (as opposed to languages like Java, C# or Typescript), Python will not inform you about this syntax error.
How to read the first element of this JSON?
when the file appears like this
for i in data[1]:
print("Testing"+i['LocalObservationDateTime'])
This is not working for me.
Below is the JSON file
[
{
"LocalObservationDateTime":"2022-09-15T19:05:00+02:00",
"EpochTime":1663261500,
"WeatherText":"Mostly cloudy",
"WeatherIcon":6,
"HasPrecipitation":false,
"PrecipitationType":"None",
"IsDayTime":true,
"Temperature":{
"Metric":{
"Value":11.4,
"Unit":"C",
"UnitType":17
},
"Imperial":{
"Value":52.0,
"Unit":"F",
"UnitType":18
}
},
"RealFeelTemperature":{
"Metric":{
"Value":8.4,
"Unit":"C",
"UnitType":17,
"Phrase":"Chilly"
}
}
},
{
"LocalObservationDateTime":"2022-09-16T19:05:00+02:00",
"EpochTime":1663261500,
"WeatherText":"Mostly cloudy",
"WeatherIcon":6,
"HasPrecipitation":false,
"PrecipitationType":"None",
"IsDayTime":true,
"Temperature":{
"Metric":{
"Value":11.4,
"Unit":"C",
"UnitType":17
},
"Imperial":{
"Value":52.0,
"Unit":"F",
"UnitType":18
}
},
"RealFeelTemperature":{
"Metric":{
"Value":8.4,
"Unit":"C",
"UnitType":17,
"Phrase":"Chilly"
}
}
}
]
This can happen if a comma is missing. I ran into it when I had a list of two-tuples, each of which consisted of a string in the first position, and a list in the second. I erroneously omitted the comma after the first component of a tuple in one case, and the interpreter thought I was trying to index the first component.
Converting the lower case letters to upper:
str1 = "Hello How are U"
new_str = " "
for i in str1:
if str1[i].islower():
new_str = new_str + str1[i].upper()
print(new_str)
Error :
TypeError: string indices must be integers
Solution :
for i in range(0, len(str1))
// Use range while iterating the string.

Categories