Thursday, December 05, 2019

Significant changes for some error messages in Python 3.8

As I work on including more exceptions in Friendly-traceback, I am mostly pleasantly surprised by generally more precise error messages.  For example, in Python 3.7, the following

__debug__ = 1

would yield "SyntaxError: assignment to keyword" which likely would baffle almost everyone looking up the list of Python keywords.   In Python 3.8, that message has been replaced by the more precise: "SyntaxError: cannot assign to __debug__". Much better, in my opinion, even though one may be surprised to learn about this constant.

However, today as I was working on adding another case, I came accross the following:



This change is ... unexpected.  And the "helpful hint", is not so helpful in this case.  However, I can guess as to how it came about.  It will be a challenge to provide a "friendly" explanation that does not lead the users looking for an incorrect solution to their problem.

Edit: Based on my own (limited) experience working on Friendly-traceback, I do realize that trying to provide helpful hints to assist programmers in fixing code that raises exceptions is a very difficult problem.  My task, with Friendly-traceback, is generally made much easier thanks to accurate and usually helpful error messages provided by Python. So, please do not read this post and conclude that I am dismissive of the efforts of the Python core developers in this area. 

Tuesday, December 03, 2019

Friendly-traceback, Real Python, Pycon, and more

After an interruption that lasted a few months, I've finally been able to return to programming, more specifically working mostly on Friendly-traceback. For those that do not know Friendly-traceback: it aims to replace the sometimes obscure traceback generated by Python with something easier to understand. Furthermore, Friendly-traceback is designed with support for languages other than English so that, in theory, beginners (who are the main target audience for Friendly-traceback) could benefit no matter what their native language is ... provided someone would have done the translation into that language, of course.

As of now, 75 different cases have been tested; you can find them in the documentation.  [If you have suggestions for improvements, please do not hesitate to let me know.]

Recently, a post by Real Python on SyntaxError has given me added impetus to work on Friendly-traceback. I'm happy to report that, other than the cases mentioned dealing with misspelled or missing keywords, all of the other examples mentioned in that post can be analyzed by Friendly-traceback with an appropriate explanation provided. Note that these are not hard-coded examples from that post, so that any similar cases should be correctly identified.

Friendly-traceback works with Python 3.6, 3.7 and 3.8.  As I included support for 3.8, I found that some error messages given by Python changed in this newer version, and were generally improved. However, this meant that I had to change a few things to support all three versions.

Working on Friendly-traceback, and on AvantPy, has been so far a fun learning experience for me. I was hoping and looking forward to submit a talk proposal dealing with both these project to the Pycon Education Summit, as I thought that both projects would be of interest to Python educators. However, the call for proposals is focused on people's experience with actual teaching case studies about how teachers and Python programmers have implemented Python instruction in their schools, communities, and other places of learning ... So, definitely no interest in talks about tools like those I create. I certainly do understand the reason for this choice, but I cannot help but feeling disappointed as I was definitely hoping to get an opportunity to give a talk on these projects, and exchange ideas with interested people afterwards.

I did submit a proposal for a reasonably advanced and more technical talk dealing with import hooks and exception hooks, to share what I have learned (while working on Friendly-traceback and AvantPy) with the Pycon crowd. The last time I gave a talk at Pycon was in 2009 and the "competition" to have a talk accepted was much less than what it is now.  Giving a talk is the only way that I can justify taking a leave from my day job to attend Pycon, something I really miss.

Back to Real Python ... I remember purchasing some books from them some time in 2014, and, more recently, I did the same for the "course" on virtual environments. I had never bothered with virtual environments until recently and thought that, if I actually paid to get some proper tutorial, I would have no excuse not to start using virtual environments properly.  The "course" that I bought was well put together.  Compared to standard books, I find it a bit overpriced for the amount of material included. 

As a pure Python hobbyist, I appreciate the material Real Python make freely available, but do find their membership price rather steep.  However, I did note that their tutorial writers could get free access to their entire collection ... 

;-) Perhaps I should offer to write tutorials on 1) using import hooks; 2) using exception hooks; 3) designing libraries with support for translations in a way that they "play well together" -- all topics I had to figure out on my own.  While there are tutorials about translation support, I found that all of them give the same gettext-based approach of defining a global function named "_" which works very well for isolated packages, but can fail spectacularly in some corner cases as I found out while developing Friendly-traceback and AvantPy. 

However, writing clear tutorials takes a lot of time and effort, and is not as fun to me as writing code. So, I think that, for now, I'll just go back to add support for more Python exceptions in Friendly-traceback - and hope that I will have soon to focus my entire free time in putting together material for a Pycon talk.

Tuesday, June 04, 2019

Abolishing SyntaxError: invalid syntax ...

... and other cryptic messages.

Do you remember when you first started programming (possibly with Python) and encountered an error message that completely baffled you? For some reason, perhaps because you were required to complete a formal course or because you were naturally persistent, you didn't let such messages discourage you entirely and you persevered. And now, whenever you see such cryptic error messages, you can almost immediately decipher them and figure out what causes them and fix the problem.

Congratulations, you are part of an elite group! Even a large number of people who claim that they can program are almost certainly less capable than you are.

Given your good fortune, would you mind donating 5 to 10 minutes of your time to help countless beginners that are struggling in trying to understand Python error messages?  All you need to do is:


  1. Glance through of exceptions on this page and use your experience to find a case not covered. Note that this excludes SyntaxError cases, some of which are included here, but would require more of your time.
  2. Fire up your favourite Python REPL and write some simple code that generates an exception not already covered.  Perhaps, something like ValueError: could not convert string to float: 'a'
  3. Create a new issue with the error message as the title, including the code that generated the exception in the description of the issue together with a simple explanation (in a couple of sentences) of what the error message means.  Imagine that you are writing an explanation for the twelve year old child of your best friend who has expressed some interest in learning how to program.  This simple explanation is the most important part ... however, do not worry about getting it absolutely perfect as it will likely be improved upon based on feedback from future "real beginners".
  4. Go back to whatever you were doing before, knowing that the few minutes you have invested will cumulatively save many hours to future generation of programmers that encounter the exception you wrote about.
It should go without saying that contributions that require more time and effort that what is described above are also very welcome!  If you feel particularly ambitious, you can certainly improve the existing code that currently analyses cases of SyntaxError: invalid syntax, which currently handles only a few cases, and should be seen more as a prototype/proof-of-concept.

Future plans for friendly-traceback


Friendly-traceback is being written so that it could be easily incorporated into editors or IDEs that are designed for beginners. I intend to ensure that it can be easily added to Python's IDLE, as well as Mu and Thonny. I hasten to add that Thonny already includes an excellent tool (its "Assistant") which provides amazing feedback to beginners in some cases. Thonny's assistant uses a complementary approach to that of Friendly-traceback and it is quite likely that a future version of Friendly-traceback will include and expand upon the type of analysis performed by Thonny's assistant to help beginners. However, for the moment, the current development of Friendly-traceback is focused on breadth of coverage (i.e. increasing the number of exceptions included), providing a single most-likely explanation for each exception, rather than looking at multiple possible causes for a given exception as is done by Thonny's Assistant.

Friday, May 24, 2019

Avant-IDLE: an experiment

[Edit: this post has an embedded video, which is not visible for PlanetPython readers.]



This is a follow-up from a previous post where I showed just a screenshot made after one hacking session.  A week later, much has changed.

As noted at the end of the video, the code is not (yet) available in a public repository.  Among other things, I need to figure out what license I can use and if I can reuse all of the content from Python's version, or if I need to remove certain assets, etc.

Avant-IDLE makes use of two projects that I started recently and mentioned before on this blog:

Friendly-traceback (code, documentation) and AvantPy (code, documentation). AvantPy itself depends on Friendly-traceback.

Both Friendly-traceback and AvantPy welcome contributions.  Publishing this video about AvantPy is a way to bring more attention to these other two projects.


Going forward with Avant-IDLE

As for Avant-IDLE, if I can go forward with it:

  • I would like to translate its menus.
  • I would like to add syntax coloring for each individual dialect: this would likely mean some significant change from the way that syntax coloring is done in IDLE.
  • I would like to have friendly tracebacks make use of color, like iPython does.
  • I would like to add line numbers to the file editor.
  • etc.
I might have to remove the debugger, as it makes little sense to have someone entering code in their native language and suddenly have to deal with standard Python since that is the code that is truly executed.  I think that, by the time someone is ready to use a debugger, they are definitely ready to use Python itself.

In an ideal world, save for the "dialect converter" demonstrated in the video, I would like for the rest of Avant-IDLE to be in a single window, with files in tabs and the interpreter below, like Al Sweigart described:


However, that last idea might be something simply too ambitious. After all, Al Sweigart, who is far more competent and productive than I am, never managed to get that project off the ground. The more the code base from Avant-IDLE diverges from that of IDLE itself, the more difficult it will become to incorporate code changes made by Python's core developers to improve IDLE.


Making the code public

Even if I figure out all I need to do to make Avant-IDLE public, I am somewhat hesitant in doing so.

There is no doubt in my mind that I can continue working and improving both Friendly-traceback and AvantPy.  I truly believe that Friendly-traceback could be very helpful for Python beginners.  It could be integrated in other beginner-friendly editors, like Mu or Thonny - two fantastic projects.

I think that AvantPy could be useful for beginners as well ... but I do admit that it is a bit quirky.

When it comes to Avant-IDLE itself, as the saying goes, I don't want to bite more than I can chew, and find out that I created something which I cannot maintain. I do realize my limitations: I am just a hobbyist with no formal training in programming and who likes to do quirky experiments in his spare time. Publishing code on Github and/or making it available at Pypi automatically raises people's expectations, and demands on one's time.

Still, if this video can inspire you to create something useful for beginners, it will have been worthwhile.  Even more so if it inspires you to contribute to either Friendly-traceback or AvantPy, ;-)


Comments?

If you have any constructive criticism, or suggestions to offer, please feel free to do so, either on this blog, or by email.

Friday, May 17, 2019

Idle hacking - part 1



  1. File test_py.pyfr.  The pyfr extension indicates that this is written in the "French Python" dialect. Since this is the main file we'll run, it will also automatically set the language to French. This is all done by AvantPy.
  2. "afficher" is the French version of "print"
  3. "import" is the normal Python keyword; we can mix and match keywords from a given dialect with the normal Python ones.  Here, we are importing a module whose base name is "upper".
  4. The constant "a" is defined.
  5. File "upper.pyupper"; the only file whose base name is "upper" - thus, the one that will be imported. The "pyupper" extension indicates that the dialect is an "upper case" version of Python - designed for testing.
  6. The code that will be run when the file is imported.
  7. Output from both files.
  8. "a" is defined.
  9. We made a syntax mistake. However, Friendly-traceback is there to help us understand what went wrong ... picking up the default language to use (French) from that first file that was run.

All this was run with a crudely hacked version of Idle. I'm still confused with the communications done with the RPCServer and the TPCServer, having never looked at similar code before.  So, I haven't been able to make it do all that I wanted in this first hacking session. Hopefully, there will be more to come ...

Wednesday, May 15, 2019

Friendlier tracebacks

When beginners run programs that generate Python tracebacks, they are almost always confused by what the information shown and have no clue as to what this all means. More experienced programmers can sometimes extract enough information directly from tracebacks to figure out what what wrong, but they will often have to resort to inserting a few print calls and running their program again to truly figure out what went wrong and how to fix it. (A minority of programmers might eschew using print calls and use a debugger instead.)

In order to make tracebacks more useful for them, some advanced programmers have designed tools to add more information so that simply looking at the enhanced traceback might be sufficient to diagnose properly the problem.  These tools include better_exchook, infi.traceback, rich-traceback, stackprinter, as well as the beautiful better-exceptions, and many others including Python's own cgitb module.  While there is no doubt that the additional information provided by these tools is useful for advanced programmers, it would likely only add to their confusion if it were used by beginners.

Friendly-traceback, a project I have been working on, and mentioned briefly in an addendum of my last post, aims at improving the situation for beginners.


A quick example


Have a look at the following Python traceback that might be generated by code written by a beginner.



Compare this with the following when using Friendly-traceback's own REPL



The only thing that is shown in exactly the same way is the line showing the exception name an a message. Everything else can be made available in other languages as shown below with a French translation.




Currently, Friendly-traceback can offer a more helpful message than a normal Python traceback in approximately 50 different cases, most of which are cases of either TypeError or SyntaxError. My goal is to eventually include explanations for all standard Python exceptions, and include as many sub-cases as possible.

As shown above, it is possible to translate the information in any language. Currently, only English and French are included; inclusion of other languages will require the help of volunteers.

If you write programs with your own custom exceptions, it is possible to write them so that they could be interpreted correctly by Friendly-traceback.  I have done so in another project, AvantPy, which I mentioned previously here. AvantPy includes 10 custom exceptions.

Both AvantPy and Friendly-traceback are available from Pypi. Contributors are most definitely welcome.