Skip to content

Commit 265e686

Browse files
committed
added explanation about errors and the IDE
1 parent 14b4132 commit 265e686

17 files changed

+208
-7
lines changed

text/main/basics/gettingStarted/examples/examples.tex

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
\begin{sloppypar}%
6666
Alternatively to downloading a \texttt{zip} archive with the examples from this book, you can also directly create a new project in \pycharm\ by cloning (basically, downloading) the repository as illustrated in \cref{fig:cloningExamples}.
6767
In the \pycharm\ welcome screen, you click \menu{Clone Repository} as shown in \cref{fig:clone01welcomeToPycharm}.
68-
In the next dialog, you have to select a source \menu{URL:}, which will be \programmingWithPythonCodeRepo.
68+
In the next dialog, you have to select a source \menu{URL:}, which will be \expandafter\url{\programmingWithPythonCodeRepo}.
6969
You also need to choose a \menu{Directory:} where the new project should be located.
7070
All the contents of the examples repository will be downloaded into this directory as well.
7171
In \cref{fig:clone02selectRepoAndDestination}, I selected \textil{/tmp/programmingWithPythonCode}, i.e., a directory on my partition for temporary files.

text/main/basics/variables/assignment/assignment.tex

+2-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@
288288
Given that the constant~\pythonilIdx{pi} from the \pythonilIdx{math} module is \pythonil{3.141592653589793}, we find that the first four digits are correct and that the number is only off by only 0.0045\%!
289289
For your convenience, we also showed the results when executing the program in \pycharm\ or the \ubuntu\ \pgls{terminal} in \cref{fig:variables:liuHuiPi}.
290290
They are obviously identical.
291-
Therefore, in the future, we will no longer add these screenshots and only print code and output pairs like~\cref{lst:variables:pi_liu_hui,exec:variables:pi_liu_hui}.%
291+
Therefore, in the future, we will only very sporadically add such screenshots.
292+
Instead, we will usually only print code and output pairs like~\cref{lst:variables:pi_liu_hui,exec:variables:pi_liu_hui}.%
292293
%
293294
\endhsection%
294295
%
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
\hsection{Interlude: Finding Errors in your Code with the IDE}%
2+
\label{sec:errorsInIde}%
3+
%
4+
\gitPythonAndErrorOutput{\programmingWithPythonCodeRepo}{variables}{assignment_wrong.py}{--args format}{variables:assignment_wrong}{%
5+
A variant of \cref{lst:variables:assignment} with an error: \pythonil{int_var} is accidentally spelled as \pythonil{intvar} in one location.}%
6+
%
7+
\begin{figure}%
8+
\centering%
9+
%
10+
\subfloat[][%
11+
We run the program \textil{assignment_wrong.py} given in \cref{lst:variables:assignment_wrong} in the \pycharm\ \pgls{IDE} by clicking on the \pycharmRun\ button or by pressing~\keys{\shift+F10}.%
12+
\label{fig:errorsInIde01runProgram}%
13+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde01runProgram}}}%
14+
%
15+
\floatRowSep%
16+
%
17+
\subfloat[][%
18+
The output in the run window is the same as given in \cref{exec:variables:assignment_wrong}. %
19+
It is the \emph{first} way to find out what went wrong. %
20+
It tells us what went wrong and even suggests how to fix it:~\emph{\pythonilIdx{NameError}: name \inSQuotes{\pythonil{intvar}} is not defined. Did you mean: \inSQuotes{\pythonil{int_var}}?} %
21+
It also tells us the exact file and line where the error occurred, namely in line~12 of file \textil{assignment_wrong.py}.%
22+
\label{fig:errorsInIde02exception}%
23+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde02exception}}}%
24+
%
25+
\floatRowSep%
26+
%
27+
\subfloat[][%
28+
If we click on the linked file location, it takes us to where the error occurred. %
29+
The incorrectly typed word is (and always was) underlined with red color. %
30+
Looking for underlined words is the \emph{second} method to find errors in code!%
31+
This should have told us already that something is fishy without the need to even run the program in the first place.%
32+
\label{fig:errorsInIde03underlined}%
33+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde03underlined}}}%
34+
%
35+
\caption{How the \pgls{IDE} can help us finding errors.}%
36+
\label{fig:errorsInIdeA}%
37+
\end{figure}%
38+
%
39+
\begin{figure}%
40+
\ContinuedFloat%
41+
\centering%
42+
%
43+
\subfloat[][%
44+
The \pgls{IDE} also informs us that something is wrong by displaying the small red~\pycharmErrorsSymbol~icon in the top-right corner. %
45+
This is the \emph{third} way to find errors. %
46+
We click on it\dots%
47+
\label{fig:errorsInIde04errors}%
48+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde04errors}}}%
49+
%
50+
\floatRowSep%
51+
%
52+
\subfloat[][%
53+
{\dots}and it takes us to the list of potential errors that it has detected. %
54+
Here, it tells us that there is an \emph{Unresolved reference \inSQuotes{intvar}} at line~12 of the file. %
55+
We click on this note\dots%
56+
\label{fig:errorsInIde05errorsList}%
57+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde05errorsList}}}%
58+
%
59+
%
60+
\floatRowSep%
61+
%
62+
\subfloat[][%
63+
{\dots}and it takes us again to the dodgy line.%
64+
\label{fig:errorsInIde06errorsListToLine}%
65+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde06errorsListToLine}}}%
66+
%
67+
\caption{How the \pgls{IDE} can help us finding errors.}%
68+
\label{fig:errorsInIdeB}%
69+
\end{figure}%
70+
%
71+
\begin{figure}%
72+
\ContinuedFloat%
73+
\centering%
74+
%
75+
\subfloat[][%
76+
The \emph{fourth} way in which the \pycharm\ \pgls{IDE} can help us to discover errors are small red marks at the right-hand side. %
77+
Holding the mouse cursor over these lines will open a small view with the suggested error message.%
78+
\label{fig:errorsInIde07errorMark}%
79+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde07errorMark}}}%
80+
%
81+
\floatRowSep%
82+
%
83+
\subfloat[][%
84+
The \emph{fifth} way to get a list of potential errors in \pycharm\ is to click on the \pycharmErrorsButton~button in the side menu on the left-hand side or to press~\keys{\Alt+6}.
85+
\label{fig:errorsInIde08sidebar}%
86+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde08sidebar}}}%
87+
%
88+
\floatRowSep%
89+
%
90+
\subfloat[][%
91+
This again takes us to the list of potential errors.%
92+
\label{fig:errorsInIde09sidebarToView}%
93+
]{\tightbox{\includegraphics[width=0.9\linewidth]{\currentDir/errorsInIde09sidebarToView}}}%
94+
%
95+
\caption{How the \pgls{IDE} can help us finding errors.}%
96+
\label{fig:errorsInIdeC}%
97+
\end{figure}%
98+
%
99+
Before we depart from \pycharm\ screenshots, however, we will visit one absolutely crucial functionality that modern \pglspl{IDE} provide:
100+
They help us to find errors in the code.
101+
Errors are common.
102+
They happen all the time.
103+
Every programmer sometimes makes a typo, accidentally switches the order of parameters of a function, stores a \pythonil{float} in an \pythonil{int} variable, and so on.
104+
Some errors are obvious and easy to fix.
105+
Some require more serious debugging (see \cref{sec:dunder:debugging}).
106+
In many cases, however, our \pgls{IDE} can already show us what and where the mistake happened.
107+
108+
In \cref{lst:variables:assignment_wrong}, we prepared program \textil{assignment_wrong.py}, a variant of \textil{assignment.py}~(\cref{lst:variables:assignment}) with an error.
109+
For the sake of the example, let us assume that the programmer made a type in line~12 of the program:
110+
They misspelled \pythonil{int_var} and \pythonil{intvar}.
111+
Executing the program with the error leads to the output given in \cref{exec:variables:assignment_wrong}.
112+
113+
The questions now are:
114+
How can we see this same error in our \pycharm\ \pgls{IDE}?
115+
Could we have found this error even without executing the program?
116+
117+
To answer these questions, we open the program \textil{assignment_wrong.py} given in \cref{lst:variables:assignment_wrong} in the \pycharm\ \pgls{IDE}.
118+
We execute this program manually by clicking on the \pycharmRun\ button or by pressing~\keys{\shift+F10} in \cref{fig:errorsInIde01runProgram}.
119+
As you can see, the output in the run window is the same as given in \cref{exec:variables:assignment_wrong}~(\cref{fig:errorsInIde02exception}).
120+
Reading this output is the \emph{first} way to find out what went wrong.
121+
The text that appeared tells us what went wrong and even suggests how to fix it.
122+
It says:~\emph{\inQuotes{\pythonilIdx{NameError}: name \inSQuotes{\pythonil{intvar}} is not defined. Did you mean: \inSQuotes{\pythonil{int_var}}?}}
123+
This is already pretty clear.
124+
We accessed some variable (name), \pythonil{intvar}, which has not been defined or assigned.
125+
It simply does not exist.
126+
The \python\ interpreter then checks whether some similar name exists.
127+
It found that there is a variable named \pythonil{int_var}.
128+
Even more, it also tells us the exact file and line where the error occurred, namely in line~12 of file \textil{assignment_wrong.py}!
129+
With this information, we have a good chance of finding the mistake.
130+
The so-called \pythonil{Exception} \pgls{stackTrace} that it prints thus not just tells us the error, a probable cause, and the most-likely location that caused the error.
131+
We will discuss this topic in-depth later in \cref{sec:exceptions}, but even at this stage, the message here is pretty clear.%
132+
%
133+
\bestPractice{readErrorMessage}{Always carefully \emph{read} error messages. %
134+
They often provide you very crucial information where to look for the mistake. %
135+
Not reading error messages is wrong.%
136+
}%
137+
%
138+
In the run console of \pycharm, we click on the linked file location.
139+
This takes us to where the error occurred in \cref{fig:errorsInIde03underlined}.
140+
When looking at this line, we notice that the incorrectly typed word is (and always was) underline with red color.
141+
This should have told us already that something is fishy without the need to even run the program in the first place.%
142+
%
143+
\bestPractice{redUnderline}{%
144+
When writing code, we should always check whether the \pgls{IDE} notifies us about potential errors. %
145+
In the case of \pycharm, these are often underlined in red or yellow color. %
146+
We should always check all such marks!%
147+
}%
148+
%
149+
So we already know two ways in which we can find errors in our code with the help of our \pgls{IDE}.
150+
But there are even more ways.
151+
152+
The \pgls{IDE} also informs us that something is wrong by displaying the small red~\pycharmErrorsSymbol~icon in the top-right corner, as shown in \cref{fig:errorsInIde04errors}.
153+
Clicking on this symbol is the third way to find errors.
154+
This will take us to the list of potential errors that it has detected in \cref{fig:errorsInIde05errorsList}.
155+
Here, \pycharm\ tells us that there is an \emph{\inQuotes{Unresolved reference \inSQuotes{intvar}}} at line~12 of the file.
156+
We can also click on that note, and it takes us again to the dodgy line in \cref{fig:errorsInIde06errorsListToLine}
157+
158+
The fourth method in which the \pycharm\ \pgls{IDE} can help us to discover errors are small red marks at the right-hand side of our editor window, shown in \cref{fig:errorsInIde07errorMark}.
159+
Holding the mouse cursor over these lines will open a small view with the suggested error message.
160+
161+
The fifth way to get a list of potential errors in \pycharm\ is to click on the \pycharmErrorsButton~button in the side menu on the left-hand side or to press~\keys{\Alt+6}, as illustrated in \cref{fig:errorsInIde08sidebar}.
162+
This again takes us to the list of potential errors in \cref{fig:errorsInIde09sidebarToView}.
163+
%
164+
\usefulTool{ideForErrors}{%
165+
The \pgls{IDE} and the error messages (\pythonilIdx{Exception} \pglspl{stackTrace}) are your most important tools to find errors. %
166+
Read error messages. %
167+
If your \pgls{IDE} -- regardless whether it is \pycharm\ or something else -- annotates your code with some marks, then you should check every single one of them.%
168+
}%
169+
%
170+
These tools make it much much easier to find errors.
171+
You can guess the importance of such features also by how many different ways \pycharm\ implements to get you to click and investigate its list of proposed errors and warnings.
172+
As mentioned in \cref{bp:readErrorMessage,bp:redUnderline}, using the \pgls{IDE} features for error discovery and detection is incredibly important.
173+
Even if your program executes as expected, there still might be hidden errors in the code.
174+
Sometimes, you cannot easily tell whether the output of a program is correct.
175+
And the output you see might actually be wrong.
176+
Sometimes, there might be some incorrect instructions in your program that just weren't used in your last execution.
177+
So even correct program output does not guarantee that the program itself is correct.
178+
Therefore, always checking each and every piece of code that your \pgls{IDE} marks as dodgy is very important.
179+
Make sure that you full understand all error and warning messages.
180+
Always fix them when necessary (obviously).
181+
Even where you deem the warnings as false-positives, try to fix them anyway.
182+
On one hand, \emph{you} might wrong on.
183+
On the other hand, having fewer warnings and false-positive suspected errors makes it easier to find the actual problem if an actual problem happens.%
184+
%
185+
\FloatBarrier%
186+
\endhsection%
187+
%
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

text/main/basics/variables/multiAndSwap/multiAndSwap.tex

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
\gitPythonAndOutput{\programmingWithPythonCodeRepo}{variables}{multi_and_swap.py}{--args format}{variables:multi_and_swap}{%
44
A \python\ program assigning multiple values to multiple variables and using the same method to swap variable values.}%
55
%
6+
Let us return to the topic of variables and assignments.
67
In \python, we can assign values to multiple variables at once.
78
In this case, we separate both the variable names and the values with commas.
89
The first line (\pythonil{a, b = 5, 10}\pythonIdx{=!multiple}\pythonIdx{,}) in \cref{lst:variables:multi_and_swap} assigns the values~\pythonil{5} and~\pythonil{10}, respectively, to the variables~\pythonil{a} and~\pythonil{b}, respectively.

text/main/basics/variables/typesAndTypeHints/typesAndTypeHints.tex

+11-2
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@
220220
A variant of \cref{lst:variables:types} which has been improved by adding type annotations.}%
221221
%
222222
\gitOutputTool{\programmingWithPythonCodeRepo}{.}{_scripts_/mypy.sh variables variable_types_hints.py}{variables:variable_types_hints:mypy}{%
223-
The results of static type checking with \mypy\ of the program given in \cref{lst:variables:types_hints}.}
223+
The results of static type checking with \mypy\ of the program \textil{variable_types_hints} given in \cref{lst:variables:types_hints}.}
224224

225225
For the sake of completeness, let us also annotate \cref{lst:variables:types} with \pglspl{typeHint} as a small exercise.
226226
The variable \pythonil{int_var}, in which we want to store the integer value~\pythonil{8}, will be annotated with \pythonil{: int}.
@@ -240,7 +240,16 @@
240240
However, if you are a student attending one of my courses, consider them as mandatory.
241241
Their advantage is that they allow us to find many (though by far not all) logical errors.
242242
They make the code easier to read and easier to understand.
243-
Therefore, from my perspective, \cref{bp:typeHints} \emph{always} applies.%
243+
Therefore, from my perspective, \cref{bp:typeHints} \emph{always} applies.
244+
245+
\gitOutputTool{\programmingWithPythonCodeRepo}{.}{_scripts_/mypy.sh variables assignment_wrong.py}{variables:assignment_wrong:mypy}{%
246+
The results of static type checking with \mypy\ of the program \textil{assignment_wrong} given in \cref{lst:variables:assignment_wrong}.}%
247+
%
248+
For the sake of completeness, we also apply \mypy\ to the program \textil{assignment_wrong} given in \cref{lst:variables:assignment_wrong} that we used to illustrate the use of the \pycharm\ \pgls{IDE} in finding bugs.
249+
The output given in \cref{exec:variables:assignment_wrong:mypy} informs us about the same error we encountered back in \cref{sec:errorsInIde}:
250+
\emph{\inQuotes{Name \inQuotes{intvar} is not defined.}}
251+
With the \pgls{IDE} and \mypy, we now have independent tools that can help us to discover errors in our code.
252+
The more such tools we have \emph{and actively use}, the more likely it is that we can produce error-free programs.%
244253
%
245254
\FloatBarrier%
246255
\endhsection%

text/main/basics/variables/variables.tex

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
For this purpose, variables exist.%
1010
%
1111
\hinput{assignment}{assignment.tex}%
12+
\hinput{errorsInIde}{errorsInIde.tex}%
1213
\hinput{multiAndSwap}{multiAndSwap.tex}%
1314
\hinput{typesAndTypeHints}{typesAndTypeHints.tex}%
1415
\hinput{identity}{identity.tex}%

text/main/controlFlow/exceptions/exceptions.tex

+4-2
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
Notice that the actual path to the files will be different depending on where the source code of the examples is located.
176176
We replaced the variable part of the path with~\inQuotes{\{\dots\}}.
177177
The remaining part of the path, \textil{exceptions/use_sqrt_raise.py}, clearly points out the calling program as the culprit \cref{lst:exceptions:use_sqrt_raise}.
178+
We already took a glimps on how useful the \pgls{stackTrace} is back in \cref{sec:errorsInIde}.
178179
Indeed, the following line of text identifies that instruction in \cref{lst:exceptions:use_sqrt_raise} that caused the error and even marks the offending function invocation by underlining it with \textil{{^}{^}{^}{^}{^}{^}{^}{^}{^}{^}{^}{^}}.
179180
Below that, we get to see the context of our \pythonil{sqrt} function:
180181
First, the path to its module is given (ending in \textil{exceptions/sqrt_raise.py}) and it is pointed out that the exception was raised in line~15.
@@ -195,7 +196,8 @@
195196
%
196197
\bestPractice{exceptionStackTrace}{%
197198
The \pgls{stackTrace} and error information printed on the \python\ console in case of an uncaught exception are essential information to identify the problem. %
198-
They should \emph{always} be read and understood before trying to improve the code.%
199+
They should \emph{always} be read and understood before trying to improve the code. %
200+
See also \cref{bp:readErrorMessage}.%
199201
}%
200202
%
201203
In our original \pythonil{tuple} of inputs that we iteratively passed to \pythonil{sqrt}, the last three elements are \pythonilIdx{inf}, \pythonilIdx{nan}, and \pythonil{-1.0}.
@@ -759,7 +761,7 @@
759761
.4 \pythonilIdx{IndexError}\DTcomment{a sequence index is out of range, see, e.g., \cref{sec:strBasicOperations}}.
760762
.4 \pythonilIdx{KeyError}\DTcomment{a dictionary key is not found, see, e.g., \cref{sec:dictionaries}}.
761763
.3 \pythonilIdx{MemoryError}\DTcomment{when we are out of memory}.
762-
.3 \pythonilIdx{NameError}\DTcomment{e.g., when reading an unassigned variable, see, e.g., \cref{lst:exceptions:try_multi_except}}.
764+
.3 \pythonilIdx{NameError}\DTcomment{e.g., when reading an unassigned variable, see, e.g., \cref{lst:variables:assignment_wrong,lst:exceptions:try_multi_except}}.
763765
.4 \pythonilIdx{UnboundLocalError}\DTcomment{reference to a local method or function to which no value is bound}.
764766
.3 \pythonilIdx{OSError}\DTcomment{an operating system function failed}.
765767
.4 \pythonilIdx{BlockingIOError}\DTcomment{a blocking operation is applied to an object set for non-blocking operations}.

0 commit comments

Comments
 (0)