Explicit float conversion in python gives ParseError - python

I'm learning python in Coursera, I tried the assignment for the course but am not getting the desired result. This program is supposed to extract '0.8475' and convert it to float before printing it.
text = "X-DSPAM-Confidence: 0.8475";
pos=text.find('0');
s=text[pos:len(text)];
p=0.0;
p=(float)s;
print p;
Everytime I run this code, I get a ParseError: bad input on line 5.
What am I doing wrong?

As #ZdaR mentions, the call to the float function must pass the parameter inside the parentheses as p = float(s). I tested this in Python IDLE and the program worked correctly.
Also note that you should not end lines with ; in Python. The whitespace itself will handle that for you when you start a new line.

Related

Cannot parse strings from list into floats, getting ValueError

I am writing short pygame script and I need to parse values from .cfg file, but I am not very experienced in python and I am getting ValueError and have no idea why it cannot parse the string.
I have tried writing a method to take the string and convert it to an int, if it fails convert it to float but that didn't work.
Here's the code:
def _file_read(self):
with open(os.path.join(sys.path[0], "planets.cfg")) as config:
lines = [line.replace(';', '').replace('{', '').replace('}', '').split() for line in config]
for j in range(len(lines)):
self.name.append(lines[j][0])
self.radius.append(float(lines[j][1]))
self.distance.append(float(lines[j][2]))
self.speed.append(float(lines[j][3]))
self.color.append(lines[j][4])
Here is what is inside the planets.cfg file, don't mind the values, they are made up for testing purposes.
Earth {123; 321; 0.005; (0,255,0)}
Mars {432; 234; 0.004; (255,0,0)}
I need to have a float that I can pass to a mathematical formula, but the ValueError likes the floats place a bit more.
Any idea how to handle that? I will be very grateful for any help or explanation why this error happens :)
Oh and here is the error it outputs:
File "C:/Users/Jakub/PycharmProjects/untitled/kruznice.py", line 35 in _file_read
self.radius.append(float(lines[j][1])) ValueError: could not convert string to float: 'radius'
EDIT Added error message, yeah, I am a really scatterbrained person.
EDIT #2 (Solution): So after a while I found the solution and it basically has NOTHING to do with code being wrong. I have had string values on line 2 in the planets.cfg file and somehow I forgot to save it, and was constantly thinking I am using the newer version with integers and floats only. Yes. Stupid mistakes happen. And I make lot of them.
The error is from self.color.append(float(lines[j][4])) You are trying to convert a tuple to float
Use ast module to convert it to a tuple
Ex:
from ast import literal_eval
def _file_read(self):
with open(os.path.join(sys.path[0], "planets.cfg")) as config:
lines = [line.replace(';', '').replace('{', '').replace('}', '').split() for line in config]
for j in lines:
self.name.append(j[0])
self.radius.append(float(j[1]))
self.distance.append(float(j[2]))
self.speed.append(float(j[3]))
self.color.append(literal_eval(j[4]))

Why does writing to stdout in console append the number of characters written, in Python 3?

I was just playing around with sys.stdout.write() in a Python console when I noticed that this gives some strange output.
For every write() call the number of characters written, passed to the function respectively gets append to the output in console.
>>> sys.stdout.write('foo bar')
for example results in
foo bar7 being printed out.
Even passing an empty string results in an output of 0.
This really only happens in a Python console, but not when executing a file with the same statements. More interestingly it only happens for Python 3, but not for Python 2.
Although this isn't really an issue for me as it only occurs in a console, I really wonder why it behaves like this.
My Python version is 3.5.1 under Ubuntu 15.10.
Apart from writing out the given string, write will also return the number of characters (actually, bytes, try sys.stdout.write('へllö')) As the python console prints the return value of each expression to stdout, the return value is appended to the actual printed value.
Because write doesn't append any newlines, it looks like the same string.
You can verify this with a script containing this:
#!/usr/bin/python
import sys
ret = sys.stdout.write("Greetings, human!\n")
print("return value: <{}>".format(ret))
This script should when executed output:
Greetings, human!
return value: <18>
This behaviour is mentioned in the docs here.

Base64 string format in python

I'm having an issue figuring out how to properly input base64 data into a string format in python 2.7. Here's the relevant code snippet:
fileExec = open(fileLocation, 'w+')
fileExec.write(base64.b64decode('%s')) %(encodedFile) # encodedFile is base64 data of a file grabbed earlier in the script.
fileExec.close()
os.startfile(fileLocation)
As silly as it may seem, I am required to use the string formatting in this case, due to the what this script is actually doing, but when I launch the script, I receive the following error:
TypeError: Incorrect Padding
I'm not quite sure what I need to do to the '%s' to get this to work. Any suggestions? Am I using the wrong string format?
Update: Here's a better idea of what I'm ultimately trying to accomplish:
encodedFile = randomString() # generates a random string for the variable name to be written
fileExec = randomString()
... snip ...
writtenScript += "\t%s.write(base64.b64decode(%s))\n" %(fileExec, encodedFile) # where writtenScript is the contents of the .py file that we are dynamically generating
I must use string formatting because the variable name will not always be the same in the python file we making.
That error usually means your base64 string may not be encoded properly. But here it is just a side-effect of a logic error in your code.
What you have done is basically this:
a = base64.b64decode('%s')
b = fileExec.write(a)
c = b % (encodedFile)
So you are attempting to decode the literal string "%s", which fails.
It should look more like this:
fileExec.write(base64.b64decode(encodedFile))
[edit: using redundant string format... pls don't do this in real code]
fileExec.write(base64.b64decode("%s" % encodedFile))
Your updated question shows that the b64decode part is inside of a string, not in your code. That is a significant difference. The code in your string is also missing a set of inner quotes around the second format:
writtenScript += "\t%s.write(base64.b64decode('%s'))\n" % (fileExec, encodedFile)
(notice the single quotes...)

C subprocess from Python: sub.stdin.write IOError Broken Pipe

I am getting a Broken Pipe error when writing a large quantity of data very fast to a C subprocess.
So I am running a c subprocess from a python script:
process = subprocess.Popen("./gpiopwm", stdin=subprocess.PIPE)
while True:
process.stdin.write("m2000\n")
print "bytes written"
Sectio of main loop of gpiopwm.c:
printf("1\n");
while (1) {
fgets(input,7,stdin); // Takes input from python script
printf("2\n");
numbers = input+1; // stores all but first char of input
char first = input[0]; // stores first char of input
if (first=='m') {
printf("3\n");
printf("%s\n",numbers);
}
}
However, the output from this is as follows:
1
bytes written
Traceback (most recent call last):
File "serial-receive-to-pwm.py", line 20, in <module>
process.stdin.write("m2000\n")
IOError: [Errno 32] Broken pipe
The C program evidently breaks at the fgets line, as 2 is never printed.
What have I done wrong? How can I avoid this?
EDIT:
I've updated the fgets line so that it does not include the dereference argument, but am still getting the broken pipe error.
EDIT:
input is initialized as char *input="m2000";
If you try running your C program from the console, you will see that it crashes. And if you run in a debugger, you will see that it's on this line:
fgets(*input,7,stdin);
It seems like input is a character array, and when you dereference it with *input you are passing not a pointer but a single char value. This leads to undefined behavior and the crash.
That line should have given you if not an error then a very big warning message from the compiler. Don't ignore warning messages, they are often an indicator of you doing something wrong and possibly dangerous.
A general tip: When developing a program that should be called from another program, like you do here, test the program first to make sure it works. If it doesn't work, then fix it first.
A final tip: Remember that fgets includes the newline in the destination string. You might want to check for it and remove it if it's there.
With the last edit, showing the declaration of input we know the real problem: You're trying to modify constant data, and also you want to write beyond the bounds of the data as well.
When you make input point to a literal string, you have to remember that all literal strings are read only, you can not modify a literal string. Trying to do so is undefined behavior. To make it worse, your string is only six characters long, but you try to write seven characters to it.
First change the declaration and initialization of input:
char input[16] = "m2000\n";
This will declare it as an array, located on the stack and that can be modified. Then do
while (fgets(input, sizeof(input), stdin) != NULL) { ... }
This accomplishes two things: First by using sizeof(input) as the size, you can be sure that fgets will never write out of bounds. Secondly, by using the fgets call in the loop condition the loop will end when the Python script is interrupted, and you won't loop forever failing to read anything and then work on data that you've never read.

File read reaches end of file unexpectedly

I'm translating a script from matlab, which reads a file of binary-encoded 32-bit integers and parses them appropriately. I have written the following method that is intended to mimic matlab's fread() function:
def readi(f,n):
x = zeros(n,int);
for i in range(0,n):
x[i] = struct.unpack('i',f.read(4))[0];
print x[i];
return x;
I call this function variously with n between 1 and 9 in my script as I parse out the data. My problem is that the script only gets part of the way into the file before I get this error:
x[i] = struct.unpack('i',f.read(4))[0];
struct.error: unpack requires a string argument of length 4
It appears that python thinks I have reached the end of the file. The point in execution where the error occurs is a line in a loop that has already been iterated over several times. In addition, the small portion of the file that has been parsed already matches exactly what my matlab script produces from the exact same file (not a copy). Matlab, however, is able to read a much larger dataset from the file. Does anyone have ideas on why this error is occurring?
In my own testing, whether the file was opened in binary-mode or not (surprisingly) didn't matter. The only thing I can suggest is to make sure you understand the format of the input file exactly. So in addition to reading the matlab script, it might be a good idea to look at hex dump of the file where you can see the individual bytes of raw data and be able to verify whether it matches your understanding of the layout of its contents.
Besides all that, you could try the following simplification/optimization of your readi() function which does not require the temporaryxlist and reads the bytes of all the integers in the group with one call tofile.read():
def readi(f, n):
fmt = '%di' % n
return struct.unpack(fmt, f.read(struct.calcsize(fmt)))
However I don't think it will solve your problem because it should be equivalent to what you already doing, return value-wise anyway (it doesn't print anything like yours).
One final note -- you don't need to end your lines of code with a semicolon. Python isn't like C and several other languages in that respect.

Categories