Python IP to integer conversion not working as expected - python

I am using the answer provided here to convert string IP to integer. But I am not getting expected output. Specifically, the method is
>>> ipstr = '1.2.3.4'
>>> parts = ipstr.split('.')
>>> (int(parts[0]) << 24) + (int(parts[1]) << 16) + \
(int(parts[2]) << 8) + int(parts[3])
but when I provide it the value 172.31.22.98 I get 2887718498 back. However, I expect to see value -1407248798 as provided by Google's Guava library https://google.github.io/guava/releases/20.0/api/docs/com/google/common/net/InetAddresses.html#fromInteger-int-
Also, I've verified that this service provides expected output but all of the answers provided by the aforementioned StackOverflow answer return 2887718498
Note that I cannot use any third party library. So I am pretty much limited to using a hand-written code (no imports)

A better way is to use the library method
>>> from socket import inet_aton
>>> int.from_bytes(inet_aton('172.31.22.98'), byteorder="big")
2887718498
This is still the same result you had above
Here is one way to view it as a signed int
>>> from ctypes import c_long
>>> c_long(2887718498)
c_long(-1407248798)
To do it without imports (but why? The above is all first party CPython)
>>> x = 2887718498
>>> if x >= (1<<31): x-= (1<<32)
>>> x
-1407248798

Found this post whilst trying to do the same as OP. Developed the below for my simple mind to understand and for someone to benefit from.
baseIP = '192.168.1.0'
baseIPFirstOctet = (int((baseIP).split('.')[0]))
baseIPSecondOctet = (int((baseIP).split('.')[1]))
baseIPThirdOctet = (int((baseIP).split('.')[2]))
baseIPFourthOctet = (int((baseIP).split('.')[3]))

Related

Why does Python char binding to C fails in c function?

I need to use in Python C-coded translation of string to reverse polish notation and calculation of it.
For this I do next:
import ctypes
input_string = bytes(memoryview("2 + 3.2 + 4".encode()))
result = str(self.model.functions['equal'](input_string))
where equal function is in:
def init_functions(self):
equal = self.c_lib.equal
equal.restype = ctypes.c_double
equal.argtypes = [ctypes.c_char_p]
self.functions.update({'equal': equal})
Where function in C is:
double equal(char *input) {
stack S = parseInput(input);
stack polish = toReversePolishNotation(&S);
return calculate(&polish);
}
It does calculation perfectly fine in C (checked with tests and memory leaks), always delivering the right answer.
But when I use this function in Python, it occasionally delivers some wrong output.
Sometimes it is 0, sometimes it is some strange number, sometimes it is endless cycle.
For example:
C result
Some random Python result
Strictly the next after random result in Python
More of it, my beloved example is "39.9 - 52.0". In C it is always as stated. But Python passes this string to C as "39.9 - 52.9".
I tried to set input_string = '' in Python, tried to memset char* input by '\0', tried to use different implementations of input_string:
input_string = ctypes.c_char_p("2 + 3.2 + 4".encode('utf-8'))
input_string = bytes("2 + 3.2 + 4", encoding='utf-8')
Python never delivers right answer consequently. It always fails. I don't know, if I need to free input_string somehow or something else is wrong.
The C code expects a pointer to mutable memory (probably for some tokenization). For that you need to use create_string_buffer.
input_string = ctypes.create_string_buffer(b"2 + 3.2 + 4")
See the documentation and tutorial

How to understand bytes output in python?

I am using struct for creating byte like objects out of arrays. Here is my code:
import numpy as np
import struct
a = 1
a = np.array(a,dtype=np.int32)
format_charecters = f'<1I'
bytes_ = struct.pack(format_charecters,*a.flatten())
bytes_
The code outputs:
b'\x01\x00\x00\x00'
This makes sense to me as I am using < little-endian byte-ordering and referring the following table 1 should correspond to \x01 where x represents hexadecimal.
Now when I replace 1 with 10 I get a surprising result:
b'\n\x00\x00\x00'
I was not expecting this... I thought the output will be:
b'\x0a\x00\x00\x00'
Also for some random value a = 1324233699 I get:
b'\xe33\xeeN'
Using an online decimal-hex converter I get:
4EEE33E3
How to interpret the results of my code?
The link deadshot gave perfectly explained my question. I am adding a screenshot of the table of escape characters in python so that other people can find it even if the 'tutorialspoint' site goes down.

asterisk notation doesn't work in processing.py?

I use asterisk notation in regular python as:
>>> x=(10,11)
>>> y=(12,13)
>>> z=99
>>> print(*x)
10 11
>>> print(*x, *y, z)
10 11 12 13 99
But when I try to do similar in python mode of Processing, it gives me essentially a syntax error: processing.app.SketchException: Maybe there's an unclosed paren or quote mark somewhere before this line?
p1= (20,20)
p2=(40,40)
c1 = (15,15)
c2 = (50,50)
print(p1)
print(*p1)
# bezier(**p1, **c1, **c2, **p2)
Is this not supported in Processing.PY?
It works fine, I use it all the time.
p1 = (20, 20)
p2 = (40, 40)
translate(*p1) # this works
# you can't use "star" unpacking twice like this.
# line(*p1, *p2) # this won't work!
Beware that in Python 2 print is not a function, so I have used from __future__ import print_function to make your example work on the image bellow. The print function can handle an arbitrary number of positional arguments, but again, not * "star" unpacking twice.
I have noticed in your question example ** which can be used for
keyword arguments & dictionary unpacking. It also works fine overall, but it would not work with the bezier() comment you provided. The error message might have misled you.

Strange Problem with RPy2

After installing RPy2 from
http://rpy.sourceforge.net/rpy2.html
I'm trying to use it in Python 2.6 IDLE but I'm getting this error:
>>> import rpy2.robjects as robjects
>>> robjects.r['pi']
<RVector - Python:0x0121D8F0 / R:0x022A1760>
What I'm doing wrong?
Have you tried looking at the vector that's returned?
>>> pi = robjects.r['pi']
>>> pi[0]
3.14159265358979
To expand on Shane's answer. rpy2 uses the following Python objects to represent the basic R types:
RVector: R scalars and vectors, R Lists are represented as RVectors with names, see below
RArray: an R matrix, essentially the RVector with a dimension
RDataFrame: an R data.frame
To coerce back to basic Python types look here.
As an example, I use this to convert an R List to a python dict:
rList = ro.r('''list(name1=1,name2=c(1,2,3))''')
pyDict = {}
for name,value in zip([i for i in rList.getnames()],[i for i in rList]):
if len(value) == 1: pyDict[name] = value[0]
else: pyDict[name] = [i for i in value]
In the Python interactive interpreter if an expression returns a value then that value is automatically printed. For example if you create a dictionary and extract a value from it the value is automatically printed, but if this was in an executing script this would not be the case. Look at the following simple example this is not an error but simply python printing the result of the expression:
>>> mymap = {"a":23}
>>> mymap["a"]
23
The same code in a python script would produce no output at all.
In your code you are accessing a map like structure with the code:
>>> robjects.r['pi']
This is returning some R2Py object for which the default string representation is: <RVector - Python:0x0121D8F0 / R:0x022A1760>
If you changed the code to something like:
pi = robjects.r['pi']
you would see no output but the result of the call (a vector) will be assigned to the variable pi and be available for you to use.
Looking at the R2Py documentation It seems many of the objects are by default printed as a type in <> brackets and some memory address information.
This is not an error, it's simply the 'repr' of the returned robject:
>>> r['pi']
<RVector - Python:0x2c14bd8 / R:0x3719538>
>>> repr(r['pi'])
'<RVector - Python:0x4b77908 / R:0x3719538>'
>>> str(r['pi'])
'[1] 3.141593'
>>> print r['pi']
[1] 3.141593
You can get the value of 'pi' accessing it by index
>>> r['pi'][0]
3.1415926535897931
To access element of named lists (the 'object$attribute' R syntax) I use
>>> l = r.list(a=r.c(1,2,3), b=r.c(4,5,6))
>>> print l
$a
[1] 1 2 3
$b
[1] 4 5 6
>>> print dict(zip(l.names, l))['a']
[1] 1 2 3
but I think there must be a better solution...
I found this as the only sensible, short discussion of how to go back and forth from R objects and python. naufraghi's solution prompted the following approach to converting a data.frame, which retains the nicer slicing capabilities of the dataframe:
In [69]: import numpy as np
In [70]: import rpy2.robjects as ro
In [71]: df = ro.r['data.frame'](a=r.c(1,2,3), b=r.c(4.0,5.0,6.3))
In [72]: df
Out[72]: <RDataFrame - Python:0x5492200 / R:0x4d00a28>
In [73]: print(df)
a b
1 1 4.0
2 2 5.0
3 3 6.3
In [74]: recdf = np.rec.fromarrays(df, names=tuple(df.names))
In [75]: recdf
Out[75]:
rec.array([(1, 4.0), (2, 5.0), (3, 6.2999999999999998)],
dtype=[('a', '<i4'), ('b', '<f8')])
Seems a bit off-topic at this point, but I'm not sure what the appropriate procedure would be to capture this question & answer of mine!

How to find number of bytes taken by python variable

Is there anyway i can know how much bytes taken by particular variable in python. E.g; lets say i have
int = 12
print (type(int))
it will print
<class 'int'>
But i wanted to know how many bytes it has taken on memory? is it possible?
You can find the functionality you are looking for here (in sys.getsizeof - Python 2.6 and up).
Also: don't shadow the int builtin!
import sys
myint = 12
print(sys.getsizeof(myint))
if you want to know size of int, you can use struct
>>> import struct
>>> struct.calcsize("i")
4
otherwise, as others already pointed out, use getsizeof (2.6). there is also a recipe you can try.
In Python >= 2.6 you can use sys.getsizeof.
Numpy offers infrastructure to control data size. Here are examples (py3):
import numpy as np
x = np.float32(0)
print(x.nbytes) # 4
a = np.zeros((15, 15), np.int64)
print(a.nbytes) # 15 * 15 * 8 = 1800
This is super helpful when trying to submit data to the graphics card with pyopengl, for example.
You could also take a look at Pympler, especially its asizeof module, which unlike sys.getsizeof works with Python >=2.2.
on python command prompt, you can use size of function
$ import python
$ import ctypes
$ ctypes.sizeof(ctypes.c_int)
and read more on it from https://docs.python.org/2/library/ctypes.html
In Python 3 you can use sys.getsizeof().
import sys
myint = 12
print(sys.getsizeof(myint))
The best library for that is guppy:
import guppy
import inspect
def get_object_size(obj):
h = guppy.hpy()
callers_local_vars = inspect.currentframe().f_back.f_locals.items()
vname = "Constant"
for var_name, var_val in callers_local_vars:
if var_val == obj:
vname = str(var_name)
size = str("{0:.2f} GB".format(float(h.iso(obj).domisize) / (1024 * 1024)))
return str("{}: {}".format(vname, size))
The accepted answer sys.getsizeof is correct.
But looking at your comment about the accepted answer you might want the number of bits a number is occupying in binary. You can use bit_length
(16).bit_length() # '10000' in binary
>> 5
(4).bit_length() # '100' in binary
>> 3

Categories

Resources