robertlugg / easygui

easygui for Python
http://easygui.readthedocs.org/en/master/
BSD 3-Clause "New" or "Revised" License
457 stars 116 forks source link

Exception when trying to convert <class 'int'> to text in self.textArea #131

Closed fiddybux closed 7 years ago

fiddybux commented 7 years ago

Hello!

I wonder if you can advise on this issue. I'm desperately trying to get easygui to work with some code I'm practising on. I've written standard (albeit nooby) code which works fine, as follows:

import os
import itertools
import time
import sys

input_file = open('/home/me/python/coding'
                  '/01vshort.txt', 'r')
file_content = input_file.read()
input_file.close()
os.system('clear')

file_length_question = input("\nWould you like to count the all characters\n"
                             "in the file (y/n)? ")
if file_length_question in ('y', 'Y', 'yes', 'Yes', 'YES'):
    print("\n")
    sys.stdout.write("%s" % (len("".join(file_content.split()))))
    print("\n")
elif file_length_question in ('n', 'N', 'no', 'No', 'NO'):
    print("\nOkay, no problem, let's get on with something\n"
          "else then...\n")
else:
    print("\nInvalid input! User inputted something other\n"
          "than 'Yes' or 'No'.\n")

The above code is operating on a file named "01vshort.txt" which contains a string of 0's and 1's as follows:

0
00 
1111

The answer/code result is "7", and is tested working on a much larger example containing some 250000+ characters.

However, when I try to utilise this code within easygui, I get the following error:

Exception when trying to convert <class 'int'> to text in self.textArea

The code utilising easygui is written (probably quite poorly, by me) as follows:

import easygui
import os
import sys

os.system('clear')
input_file = open('/home/me/python/coding'
                  '/01vshort.txt', 'r')
file_path = os.path.normcase('/home/me/python/coding'
                             '/01vshort.txt')
file_content = input_file.read()
input_file.close()

msg_c = ("Would you like to count the all characters in the file (y/n)?")
title_c = "Please Confirm"
msg_d = ("Okay, no problem, let's get on with something else then...")
title_d = "User-Action Confirmation"
if easygui.ynbox(msg_c, title_c):
    pass
    easygui.textbox('File Path: ' + file_path, 'Total Character Count', (
        sys.stdout.write("%s" % (len("".join(file_content.split()))))))
else:
    easygui.msgbox(msg_d, title_d, ok_button='Carry On...')

I expect it is something to do with passing a string (str) into an interger (int) field. My trouble is that my learning is rather too undeveloped to understand why this is happening.

Can you assist / advise / point to reading please?

Thanks for this great tool! I want to keep learning to implement it.

All the best.

zadacka commented 7 years ago

I think that I can see the problem here, but let's step through it so that you can get an idea of what could be wrong.

Firstly, the error message is fairly clear. At some point you have a variable of type 'int' where easygui is expecting a string. This is the difference between the integer 7, and the string '7'.

Next, let's look at the easygui call:

easygui.textbox('File Path: ' + file_path, 'Total Character Count', (
        sys.stdout.write("%s" % (len("".join(file_content.split()))))))

I suspect that this is the line where the exception is coming from. I suspect that if you look a bit more at this then the problem may pop out.

To do things more methodically, look at the arguments that the textbox class takes. It will make it much easier to read and debug your code if you assign one variable per argument and then pass them in. So something more like:

msg = 'File Path: ' + file_path
title = 'Total Character Count'
text = sys.stdout.write("%s" % (len("".join(file_content.split())))))
easygui.textbox(msg=msg, title=title, text=text, codebox=False, callback=None)

This means that you can debug to find out what some variable (like text, hint hint) actually is at the point you make the function call. It may not be a string, as the API requires.

That should be enough to show you where the problem is here, and to help you to diagnose the next one.

More generally, I'd strongly recommend getting familiar with the debugger as a way of narrowing down the scope of the problem and looking at state before and after it occurs. Picking an IDE like Pycharm can help you out a lot here. Also, if you are interested in doing some reading, then Clean Code by Bob Martin, and Pro Python by Marty Alchin are both excellent (caveats: that's my opinion only, your milage may vary).

Let me know if you still have problems here. Alternatively, feel free to close this thread if you find and fix the problem!

fiddybux commented 7 years ago

Thanks for the detailed reply, and for the advice on how to simplify for debugging purposes.

Your code-fu is strong...it is exactly this line that is causing the issues:

sys.stdout.write("%s" % (len("".join(file_content.split())))))

I know this to be true because if I remove it entirely, or just pass in a simple test statement, it works fine:

easygui.textbox('File Path: ' + file_path, 'Total Character Count', 'YoYo')

So, from my code, the line:

file_content = input_file.read()

...is bringing in the contents of the file as a series of integers. Fair enough!

Next I tried converting integers to strings, like so:

file_content = input_file.read()
file_content = str(file_content)

...or, instead of, and more simply (I thought!):

file_content = str(input_file.read())

Sadly, neither of these options yielded desirable results.

Afraid that I'm stuck again.

P.S. Those books are on my shopping wishlist now; I'll be dropping some gift hints around the season.

P.P.S. I have and will continue to try PyCharm CE, which has it's uses for sure. Right now though, I find it rather cumbersome and overwhelming. The syntax highlighting is very useful, but the inspections are way too much for me - even more information to process. I know you can turn the inspections off, but I rather prefer a simpler Sublime Text editor, with anaconda-flake8 and a terminal. Atom is also good, with Hydrogen and flake8 installed, although that too at times can be obstructive. The last time I coded seriously was COBOL in 1993 on a 80286 machine (with 33Mhz turbo mode - all anybody used it for was to make QBasic Gorillas funny and unplayable!). The point I'm trying to make here is that the curve ahead of me is steep, and I feel I need to filter out what I can't reasonably expect myself to absorb right now. I'm doing the right things I think; I was told the best way to learn is to just get coding.

zadacka commented 7 years ago

Oh, you're really close!

So, what you want (I think) is to pass the textbox the string '7' . What you are doing is:text = sys.stdout.write("%s" % (len("".join(file_content.split()))))) What you probably want to do is text=str(len("".join(file_content.split())))

It becomes difficult to follow, because you're going through a lot of different types here.

Does that make sense?

To help understand it may be useful to go through these things one at a time in the interactive prompt and print the output at each stage. Ultimately, the problem you're experiencing (the Exception when trying to convert <class 'int'> to text in self.textArea exception) is because you are passing an integer to the text kwarg of the textbox where it expects a string.

fiddybux commented 7 years ago

Thanks again, you nailed it. And, believe it or not, you're really helping me. As usual, I'm over thinking things and you've broken it down very nicely for me. So simple!

easygui.textbox('File Path: ' + file_path, 'Total Character Count', (
    str(len("".join(file_content.split())))))

That does it and works perfectly. You're a good man!

Cheers.

On 3 October 2017 at 19:29, zadacka notifications@github.com wrote:

Oh, you're really close!

So, what you want (I think) is to pass the textbox the string '7' . What you are doing is:text = sys.stdout.write("%s" % (len("".join(filecontent.split()))))) What you probably want to do is text=str(len("".join(file content.split())))

It becomes difficult to follow, because you're going through a lot of different types here.

  • file_content is a string
  • "".join(file_content) is also a string
  • len("".join(file_content)) is an int
  • "%s % len("".join(file_content)) is a string again
  • and then your actual problem comes from sys.stdout.write('stuff') which returns None in Python2 and an int (the number of characters written) in Python3. Neither looks to be what you want.

Does that make sense?

To help understand it may be useful to go through these things one at a time in the interactive prompt and print the output at each stage. Ultimately, the problem you're experiencing (the Exception when trying to convert <class 'int'> to text in self.textArea exception) is because you are passing an integer to the text kwarg of the textbox where it expects a string.

ā€” You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/robertlugg/easygui/issues/131#issuecomment-333936118, or mute the thread https://github.com/notifications/unsubscribe-auth/AX8VkQYABb4d3zCDN9KiJnPFZSAIVqHLks5son0MgaJpZM4PqBZN .

zadacka commented 7 years ago

Glad that works and the logic makes sense!

fiddybux commented 7 years ago

That's the thing about logic; it makes sense! šŸ˜‚

Might have that put on a T-shirt.

On 4 Oct 2017 7:55 am, "zadacka" notifications@github.com wrote:

Glad that works and the logic makes sense!

ā€” You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/robertlugg/easygui/issues/131#issuecomment-334065852, or mute the thread https://github.com/notifications/unsubscribe-auth/AX8VkSe2_lmLE0dZeZo4NMj0ata71SKJks5soyvmgaJpZM4PqBZN .