Python precision of float is lost while converting to string - python

I am using Scapy's sniff function for reading packets from a pcap file.
pkt=sniff(offline="a.pcap",count=1)[0]
In IDLE with pkt.time, I am able to get the time-stamp of the packet i.e. 1431063004.998014. But when I tried to convert the time-stamp to a string with str(pkt.time) or instead of pkt.time I give print pkt.time, I get only 1431063005.0.
Is it possible to get the exact time-stamp value as a string??
Note:
I looked in to decimal module. But that requires the precision number. That won't help without knowing the number of digits, I guess.

repr is another method like str which converts the whole float with precision. No need to import decimal or anything. Use it just like you use str and it returns a str object only.
>>> x = repr(pkt.time)
>>> type(x)
>>> <type 'str'>

Try this one:
"{:.6f}".format(pkt.time)

try this:
"{:.6f}".format(pkt.time)

Related

convert python string of byte data to bytes

I have a Python string of bytes data. An example string looks like this:
string = "b'\xabVJ-K\xcd+Q\xb2R*.M*N.\xcaLJU\xd2QJ\xceH\xcc\xcbK\xcd\x01\x89\x16\xe4\x97\xe8\x97d&g\xa7\x16Y\x85\x06\xbb8\xeb\x02\t\xa5Z\x00'"
It is a string, it not not bytes. I wish to convert it to bytes. Normal approaches (like encode) yield this:
b'\\xabVJ-K\\xcd+Q\\xb2R*.M*N.\\xcaLJU\\xd2QJ\\xceH\\xcc\\xcbK\\xcd\\x01\\x89\\x16\\xe4\\x97\\xe8\\x97d&g\\xa7\\x16Y\\x85\\x06\\xbb8\\xeb\\x02\\t\\xa5Z\\x00'
which leads to issues (note the addition of all the extra slashes).
I've looked through 10+ potential answers to this question on SO and only one of them works, and its a solution I'd prefer not to use, for obvious reasons:
this_works = eval(string)
Is there any way to get this to work without eval? Other potential solutions I've tried, that failed:
Option 1
Option 2
Option 3
I assume that you have python-like string representation in variable s:
s = r"b'\xabVJ-K\xcd+Q\xb2R*.M*N.\xcaLJU\xd2QJ\xceH\xcc\xcbK\xcd\x01\x89\x16\xe4\x97\xe8\x97d&g\xa7\x16Y\x85\x06\xbb8\xeb\x02\t\xa5Z\x00'"
Yes, if you eval this then you got real python bytes object.
But you can try parse it with ast module:
import ast
s = r"b'\xabVJ-K\xcd+Q\xb2R*.M*N.\xcaLJU\xd2QJ\xceH\xcc\xcbK\xcd\x01\x89\x16\xe4\x97\xe8\x97d&g\xa7\x16Y\x85\x06\xbb8\xeb\x02\t\xa5Z\x00'"
tree = ast.parse(s)
value = tree.body[0].value.value
print(type(value), value)
This will output your bytes object:
<class 'bytes'> b'\xabVJ-K\xcd+Q\xb2R*.M*N.\xcaLJU\xd2QJ\xceH\xcc\xcbK\xcd\x01\x89\x16\xe4\x97\xe8\x97d&g\xa7\x16Y\x85\x06\xbb8\xeb\x02\t\xa5Z\x00'

How to convert mathematical numbers into floats

In python, is there a way or even build in Function to convert a string into a float? Specifically:+1.488763E+01 into 14.88763 ?
What you have is a valid float literal. Convert it to a float, then convert the result back to a str
>>> '{:f}'.format(float('+1.488763E+01'))
'14.887630'
The format method is used to force the value to be represented as a fixed-point value, rather than in exponential notation. For example,
>>> str(float('1e20'))
'1e+20'
>>> '{:f}'.format(float('1e20'))
'100000000000000000000.000000'
Python does this conversion automatically. Just try it.
a = +1.488763E+01
print(a)
14.88763
It’s a decimal, it already is a float. Though if you print it, python will automatically put it in the format you want.
As long as you don’t have it as a string, it’ll be in the format you want it.
a = +1.488763E+01
print(a)
14.88763
You can use float() function
float(a)

Python : Do not include "L" at the end of the outcome for : randint(100000000000000000000, 999999999999999999999)

so far this is what i found:
from random import randint
randint(100000000000000000000, 999999999999999999999)
the output is:
922106555361958347898L
but i do not want that L there..
i can only use this as an int if there is no "L" there at the end of it.
UPDATE
would it be a better idea to generate two small numbers and then combine them if the goal is to simply have a random number that is 30 digits long ?
The reason there's an L there is because this is too large to fit into an int,* so it's a long. See Numeric Types — int, long, float, complex in the docs for more details.
So, why do you get that L, and how do you get rid of it?
Python has two different ways to turn a value into a string representation:
repr either returns the canonical source-code representation, or something like <__main__.Eggs at 0x10fbd8908>).
str returns a human-friendly representation.
For example, for strings, str('abc') is abc, while repr('abc') is 'abc'.
And for longs, str(1L) is 1, while repr(1L) is 1L.
When you just type an expression at the interactive prompt, it uses repr. But when you use the print command, it uses str. So, if you want to see the value without the L, just print it:
print randint(100000000000000000000, 999999999999999999999)
If you want to, e.g., save the string in a variable or write it to a file, you have to call str explicitly.
But if you just want to use it as a number, you don't have to worry about this at all; it's a number, and int and long values can be intermixed freely (as of Python 2.3 or so).
And if you're trying to store it in a MySQL database, whichever MySQL interface you use won't care whether you're giving it int values or long, as long as they fit into the column type.**
Or you could upgrade to Python 3.x, where there is no separate long type anymore (all integers are int, no matter how big) and no L suffix.
* The exact cutoff isn't documented anywhere, but at least for CPython, it's whatever fits into a C long on your platform. So, on most 64-bit platforms, the max value is (1<<63)-1; on the other 64-bit platforms, and all 32-bit platforms, it's (1<<31)-1. You can see for yourself on your platform by printing sys.maxint. At any rate, your number takes 70 bits, so unless someone ports Python 2.x to a platform with 128-bit C longs, it won't fit.
** Note that your values are too big to fit into even a MySQL BIGINT, so you're going to be using either DECIMAL or NUMERIC. Depending on which interface you're using, and how you've set things up, you may have to convert to and from strings manually. But you can do that with the str and int functions, without worrying about which values fit into the int type and which don't.)
If you're on the interactive prompt, explicitly print the value. The repr of the value has an L, but the str of the value doesn't.
>>> 922106555361958347898
922106555361958347898L
>>> print 922106555361958347898
922106555361958347898
The output in the REPL has an L suffixed; if you print the value, it is not displayed.
>>> from random import randint
>>> print randint(100000000000000000000, 999999999999999999999)
106315199286113607384
>>>

Printing numpy.float64 with full precision

What is the proper/accepted way to print and convert a numpy.float64 to a string? I've noticed just using print or str() will lose some precision. However, repr maintains the full precision. For example:
>>> import numpy
>>> print numpy.float64('6374.345407799015')
6374.3454078
>>> print repr(numpy.float64('6374.345407799015'))
6374.3454077990154
I assume that just calling print turns into calling str() on the float64 object. So is __str__() for numpy.float64 implemented with something like '%s' % (float(self)) or somehow casts the float64 with Python's built-in float()? I tried to quickly look around the numpy source for this but wasn't immediately obvious what was happening.
I've always thought repr() should return valid Python code that could be used by eval() to re-create the object. Is this an accepted convention? Luckily in this case numpy does not follow this convention because repr() returns just the raw number as a string instead of something like "numpy.float64('6374.345407799015')".
So, all of this confuses me. What is the correct way to convert a numpy.float64 to a string and/or print it while guaranteeing you always have the same, full precision?
The astype method works well:
>>> numpy.float64('6374.345407799015').astype(str)
'6374.345407799015'
Look into numpy.set_printoptions. Specifically,
numpy.set_printoptions(precision=15)

Python Convert an IP address encoded in Base64 to a Decimal IP address

I am very new to programming and Python so please bear with me. I have a string that is Base64 and I want to convert it to decimal. The string can come in to the script as any value, for example zAvIAQ. This value represents an IP address which is 204.11.200.1 when converted to decimal. What I want to do is convert the Base64 string to decimal and assign it to a variable so that I can use it elsewhere in the script.
I have tried to use the base64.decode function, but that just gives me a very strange text output. I have tried to use the Decimal() function but that gives me an error. After searching for several days now I haven't found a way to do this, at least not one that I can understand. Any help that you can provide would be appreciated.
First decode the base64-encoded string using decode('base64') and then decode the resulting number into an IP quartet by using socket.inet_ntoa. Like this:
>>> socket.inet_ntoa('zAvIAQ=='.decode('base64'))
'204.11.200.1'
>>> address=[ord(c) for c in base64.b64decode('zAvIAQ==')]
>>> address
[204, 11, 200, 1]
I usually use base64.b64decode(). With that you get:
In [18]: base64.b64decode('zAvIAQ==')
Out[18]: '\xcc\x0b\xc8\x01'
That is probably the weird output you were referring to. The point is that you get a byte string back, with each byte representing a value between 0 and 255. Those values might not be printable, hence the \x representation.
But as you know that these are the buckets of an IPv4 address, you go through them converting them to decimals, e.g. with the generator expression:
[ord(c) for c in ...]
and you get the more familiar representation 204, 11, 200, 1.

Categories