<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Stav Shamir</title>
    <description>The latest articles on Forem by Stav Shamir (@stavshamir).</description>
    <link>https://forem.com/stavshamir</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F153227%2Fea29587e-beb1-40d5-b9d2-3374016299e2.jpeg</url>
      <title>Forem: Stav Shamir</title>
      <link>https://forem.com/stavshamir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stavshamir"/>
    <language>en</language>
    <item>
      <title>Fix history: Edit the last bash command</title>
      <dc:creator>Stav Shamir</dc:creator>
      <pubDate>Mon, 06 Jan 2020 13:24:05 +0000</pubDate>
      <link>https://forem.com/stavshamir/fix-history-edit-the-last-bash-command-3hnk</link>
      <guid>https://forem.com/stavshamir/fix-history-edit-the-last-bash-command-3hnk</guid>
      <description>&lt;p&gt;&lt;a href="https://stavshamir.github.io/bash/fix-history-edit-the-last-bash-command"&gt;First published in my blog.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How many times have you typed a long command and quickly pressed enter, only to find out that you misspelled something or missed an argument? &lt;/p&gt;

&lt;p&gt;As a CLI user, you probably look to minimize the number of actions it takes to get a task done - so instead of rewriting the entire command (or arrowing up and changing the string), you can easily replace a string in your command with builtin bash tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Designators: Quick Substitutions
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;An event designator is a reference to a command line entry in the history list. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The quick substitution is performed by using the following syntax: &lt;code&gt;^str1^str2^&lt;/code&gt;, which means that the last command will be run again with &lt;code&gt;str1&lt;/code&gt; replaced with &lt;code&gt;str2&lt;/code&gt;. Let's see an example - say I want to copy a file named &lt;code&gt;file1.py&lt;/code&gt; to the current directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; ~/foo/bar/fle1.py &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Oops, I misspelled &lt;code&gt;file1.py&lt;/code&gt; and wrote &lt;code&gt;fle1.py&lt;/code&gt;. I can easily rerun the command with the correct file name using quick substitution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;^fle^file^
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Pressing enter prints the corrected command to the standard output and runs it as intended! You should note that the only the first matching string is replaced. There are ways to perform global replace, but the syntax is quite arcane and easy to forget. However, there is an alternative, which brings us to the next builtin.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By the way, the quote above is taken from the &lt;a href="https://www.gnu.org/software/bash/manual/html_node/Event-Designators.html"&gt;&lt;code&gt;man&lt;/code&gt; pages&lt;/a&gt;. You should look it up (it is generally a good idea to read &lt;code&gt;man&lt;/code&gt; once in while).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  fc: memorable substitution and much more
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Substitution
&lt;/h3&gt;

&lt;p&gt;Another builtin way to perform quick substitution is with the &lt;a href="%5Bhttps://www.gnu.org/software/bash/manual/html_node/Bash-History-Builtins.html%5D"&gt;&lt;code&gt;fc&lt;/code&gt; command&lt;/a&gt; (the name can be thought of as a mnemonic for 'fix command').&lt;/p&gt;

&lt;p&gt;To perform the same substitution from the previous example, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;fc&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;fle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This can be easily aliased to become even more comfortable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fc -s"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;r &lt;span class="nv"&gt;fle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;file
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I find this much more memorable than the &lt;code&gt;^str1^str2^&lt;/code&gt; syntax.&lt;br&gt;
Do note that this command performs a &lt;strong&gt;global&lt;/strong&gt; substitution, so you have to be more careful about it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Editing previous command
&lt;/h3&gt;

&lt;p&gt;Actually &lt;code&gt;fc&lt;/code&gt; can do much more. Sometimes a simple substitution is not enough to fix the command. For example, when running a long &lt;code&gt;curl&lt;/code&gt; command with payload, and you need to change some of the payload's values. &lt;/p&gt;

&lt;p&gt;Arrowing up and editing in the command line feels really inefficient, especially if you are a vim user. Yeah, I could copy the command to vim, make the changes, copy it again to the command line and run it. But that's an awful lot of steps for such a simple task. Well, this paragraph does not reside under the &lt;code&gt;fc&lt;/code&gt; title for nothing! Try running the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;fc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Yes, it does exactly what we needed it to (or maybe it opened nano, but we can fix that if needed)! Running &lt;code&gt;fc&lt;/code&gt; with no flags or arguments, opens up the previous command to edit in a predefined editor. Edit, save and exit and the fixed command will be run!&lt;/p&gt;

&lt;h3&gt;
  
  
  Changing the editor
&lt;/h3&gt;

&lt;p&gt;For one time (or always by aliasing and saving in &lt;code&gt;.bashrc&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;fc&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; ename
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;ename&lt;/code&gt; is the name of the desired editor.&lt;br&gt;
Another option is to define the environment variable FCEDIT with the desired editor. For vim that would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;FCEDIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Aborting the fix and avoiding unwanted re-reruns
&lt;/h3&gt;

&lt;p&gt;You will notice that even if you don't save the changes and quit the editor (&lt;code&gt;:q!&lt;/code&gt; in vim), the unedited command will be executed, which is probably not what you want.&lt;br&gt;
To avoid that, the editor must return a non-zero exit code. You can do this in vim by exiting with &lt;code&gt;:cq&lt;/code&gt; (or &lt;code&gt;:cq!&lt;/code&gt; if you made changes).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These are just very few ways to fix previously executed commands in bash. There are of course others (such as the more known event designator &lt;code&gt;!&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;What are your favorites? Please write them in the comments!&lt;/p&gt;

</description>
      <category>bash</category>
      <category>vim</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The other benefit of Python type annotations</title>
      <dc:creator>Stav Shamir</dc:creator>
      <pubDate>Mon, 18 Nov 2019 13:39:54 +0000</pubDate>
      <link>https://forem.com/stavshamir/the-other-benefit-of-python-type-annotations-48ib</link>
      <guid>https://forem.com/stavshamir/the-other-benefit-of-python-type-annotations-48ib</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://stavshamir.github.io/python/the-other-benefit-of-python-type-annotations/"&gt;First published in my blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Coming from statically typed languages, C and Java, I felt a little insecure writing Python code. Suddenly, silly type mismatch errors which I was used to catch during compilation were only caught (if at all, in the best case scenario) at runtime. This became especially annoying while learning new APIs or diving into a new large codebase, and made me completely reliant on documentation. While reading the docs is important on its own, I truly missed the comfortable and time-saving code completion on typing ‘.’ using IDEs such as IntelliJ.&lt;/p&gt;

&lt;p&gt;Luckily, since Python 3.5, type-annotations have been officially added to Python (&lt;a href="https://www.python.org/dev/peps/pep-0484/"&gt;PEP 484&lt;/a&gt;), and now we can write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="s"&gt;'hello {name}'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Type annotations are optional
&lt;/h2&gt;

&lt;p&gt;While having a different syntax than in C and Java, I find it rather intuitive (at least the simple cases). Importantly, the type annotations are completely optional and are ignored at runtime — meaning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can’t break the code by adding them (almost — I will elaborate in a future article)&lt;/li&gt;
&lt;li&gt;They provide no performance gain&lt;/li&gt;
&lt;li&gt;You may add them only where you see fit — I made myself a balanced rule of always annotating function signatures and module-scope variables, but I usually don’t bother to do so for local variables&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Some benefits of type annotations
&lt;/h2&gt;

&lt;p&gt;With type annotations out there for quite some time, several articles and guides were written about their benefits, of which the most common are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We can employ &lt;strong&gt;static code analysis&lt;/strong&gt; to catch type errors prior to runtime— PyCharm does this automatically, highlighting type errors (albeit they are easy to miss in my opinion). Another option, which is definitely recommended, is a useful tool named mypy, which can be run on specific type-annotated files to find type-related errors (I always run it after running my unit tests).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaner code/the code is self-documenting&lt;/strong&gt; — as Uncle Bob writes in his (very recommended) book “Clean Code”: “don’t use a comment when you can use a function or a variable”, we can now say “don’t use comments to specify a type, when you can use type annotation”. Comments tend to wear out and rot, while code is alive and must stay fresh. Change the types of the variables without changing the comment specifying the type — nothing happens. Change it without changing the type annotation? Your static analysis tool, whichever it may be, will shout at you.
&amp;gt; “don’t use a comment when you can use a function or a variable”&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  The other benefit
&lt;/h1&gt;

&lt;p&gt;One important benefit which, as I see it, should tilt your favor towards adopting this new feature if you have resisted it so far, is code completion. Early error-catching and clean code are super important, but I have seen people writing that it is more “pythonic” to write parameter assertions (which include type checking) in the beginning of a function, or that docstrings should be enough. While we can argue about that, the advantages of code completion (of course while using a good IDE, such as PyCharm) are undisputed.&lt;/p&gt;

&lt;p&gt;First, let’s see an example of such code completion. Let’s say we are writing a library modeling music objects. We have an Album class and a Track class, and in the Album class we have a method returning all tracks shorter than a specified duration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Album&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;release_year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;artist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release_year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;release_year&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;all_tracks_shorter_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let’s say I am a user of this library, and I want to print the names of all tracks shorter than 10 minutes in Wish You Were Here (which I instantiated earlier):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FRUqo8uM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bvyfcyggi4ieu2iqhzew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FRUqo8uM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bvyfcyggi4ieu2iqhzew.png" alt="code completion for untyped variables"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait a minute, was that variable called ‘name’ or ‘title’? I don’t know that! And the code completion is of no help at all — I must go to the declaration of the Track class or read its documentation — that takes time! This is the best case scenario — what if the programmer does not acknowledge she does not remember the variable name and guesses ‘name’ instead of ‘title’? It will cost even more time because this error will be found only in runtime (hopefully shes use uses TDD and catch it quickly with a pre-written test).&lt;/p&gt;

&lt;p&gt;Now what happens if we use type annotations? Let’s add only the minimal type annotation directly needed at the moment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;all_tracks_shorter_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The return value of this method is a list of Tracks, so we add ‘-&amp;gt; List[Track]’ to its signature (more about the syntax of type annotations). Let’s see what happens now on typing ‘.’:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6zciMVdN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/scmaf0u6tdxvdxd8qd3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6zciMVdN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/scmaf0u6tdxvdxd8qd3p.png" alt="code completion with type annotations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great! The IDE now knows what type this variable is, and can recommend the correct attributes — error averted! And the users of this package will have a friendlier time coding with it. Here is how the entire Album class looks like annotated (with my style of annotating):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Album&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;release_year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;artist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;artist&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release_year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;release_year&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;all_tracks_shorter_than&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Track&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h1&gt;
  
  
  Don’t use comments to specify a type, when you can use type annotation
&lt;/h1&gt;

&lt;p&gt;Wrapping up, we’ve seen that type annotations are a great addition to Python — they improve the integrity of the code, they are self-documenting code, and they may improve the productivity of the clients of your code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UaSc84Jl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fz814guqish0h21idcqz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UaSc84Jl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fz814guqish0h21idcqz.jpeg" alt="meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Further reading:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@ageitgey/learn-how-to-use-static-type-checking-in-python-3-6-in-10-minutes-12c86d72677b"&gt;How to use static type checking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.daveoncode.com/2017/03/06/writing-better-software-with-python-3-6-type-hints/"&gt;Writing better software with type hints&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>typeannotations</category>
    </item>
    <item>
      <title>Dockerizing a Flask-MySQL app with docker-compose</title>
      <dc:creator>Stav Shamir</dc:creator>
      <pubDate>Mon, 18 Nov 2019 11:41:21 +0000</pubDate>
      <link>https://forem.com/stavshamir/dockerizing-a-flask-mysql-app-with-docker-compose-kj2</link>
      <guid>https://forem.com/stavshamir/dockerizing-a-flask-mysql-app-with-docker-compose-kj2</guid>
      <description>&lt;p&gt;&lt;a href="https://stavshamir.github.io/python/dockerizing-a-flask-mysql-app-with-docker-compose/" rel="noopener noreferrer"&gt;Also published in my blog.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have heard so much about docker and its advantages, and are now eager to use it with your new web app — but where do you start?&lt;br&gt;
In this tutorial we will go through an example of taking an existing simple web app based on Flask and MySQL and making it run with Docker and docker-compose. Code is available here:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/stavshamir" rel="noopener noreferrer"&gt;
        stavshamir
      &lt;/a&gt; / &lt;a href="https://github.com/stavshamir/docker-tutorial" rel="noopener noreferrer"&gt;
        docker-tutorial
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Code for a creating a docker app with Flask and MySQL tutorial
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It is considered a best practice for a container to have only one responsibility and one process, so for our app we will need at least two containers — one for running the app itself, and one for running the database. How do we coordinate these containers? This is where docker-compose comes in. From the &lt;a href="https://docs.docker.com/compose/overview/" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Let’s start!
&lt;/h2&gt;

&lt;p&gt;If you don’t have them installed yet, install &lt;a href="https://docs.docker.com/install/linux/docker-ce/ubuntu/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; and &lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;docker-compose&lt;/a&gt;.&lt;br&gt;
We begin with the following project layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dockerize/
├── app
│   └── app.py
└── db
    └── init.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app.py&lt;/code&gt; — contains the Flask app which connects to the database and exposes one REST API endpoint&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;init.sql&lt;/code&gt; — an SQL script to initialize the database before the first time the app runs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Creating a Docker image for our app
&lt;/h2&gt;

&lt;p&gt;We want to create a Docker image for our app, so we need to create a Dockerfile in the app directory. A Dockerfile contains a set of instructions describing our desired image and allow its automatic build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use an official Python runtime as an image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.6&lt;/span&gt;

&lt;span class="c"&gt;# The EXPOSE instruction indicates the ports on which a container &lt;/span&gt;
&lt;span class="c"&gt;# will listen for connections&lt;/span&gt;
&lt;span class="c"&gt;# Since Flask apps listen to port 5000  by default, we expose it&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5000&lt;/span&gt;

&lt;span class="c"&gt;# Sets the working directory for following COPY and CMD instructions&lt;/span&gt;
&lt;span class="c"&gt;# Notice we haven’t created a directory by this name - this instruction &lt;/span&gt;
&lt;span class="c"&gt;# creates a directory with this name if it doesn’t exist&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Install any needed packages specified in requirements.txt&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Run app.py when the container launches&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; app.py /app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; python app.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does is simply as described in the file — base the image on a Python 3.6 image, expose port 5000 (for Flask), create a working directory to which requirements.txt and app.py will be copied, install the needed packages and run the app.&lt;/p&gt;

&lt;p&gt;We need our dependencies (Flask and mysql-connector) to be installed and delivered with the image, so we need to create the aforementioned requirements.txt file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask
mysql-connector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create a docker image for our app, but we still can’t use it, since it depends on MySQL, which, as good practice commens, will reside in a different container. We will use docker-compose to facilitate the orchestration of the two independant containers into one working app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a docker-compose.yml
&lt;/h2&gt;

&lt;p&gt;So let’s create a new file, docker-compose.yml, in our project’s root directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./app&lt;/span&gt;
    &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using two services, one is a container which exposes the REST API (app), and one contains the database (db).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build&lt;/code&gt;: specifies the directory which contains the Dockerfile containing the instructions for building this service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;links&lt;/code&gt;: links this service to another container. This will also allow us to use the name of the service instead of having to find the ip of the database container, and express a dependency which will determine the order of start up of the container&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports&lt;/code&gt;: mapping of &lt;code&gt;&amp;lt;host&amp;gt;:&amp;lt;container&amp;gt;&lt;/code&gt; ports.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:5.7&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;32000:3306"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./db:/docker-entrypoint-initdb.d/:ro&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;image&lt;/code&gt;: Like the FROM instruction from the Dockerfile. Instead of writing a new Dockerfile, we are using an existing image from a repository. It’s important to specify the version — if your installed mysql client is not of the same version problems may occur.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment&lt;/code&gt;: add environment variables. The specified variable is required for this image, and as its name suggests, configures the password for the root user of MySQL in this container. More variables are specified here.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports&lt;/code&gt;: Since I already have a running mysql instance on my host using this port, I am mapping it to a different one. Notice that the mapping is only from host to container, so our app service container will still use port 3306 to connect to the database.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;volumes&lt;/code&gt;: since we want the container to be initialized with our schema, we wire the directory containing our &lt;code&gt;init.sql&lt;/code&gt; script to the entry point for this container, which by the image’s specification runs all .sql scripts in the given directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are now ready to start the dockerized app! But before we do that, let’s peek at the code connecting to the database (app.py):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3306&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;database&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;knights&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mysql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are connecting as root with the password configured in the docker-compose file. Notice that we explicitly define the host (which is localhost by default) since the SQL service is actually in a different container than the one running this code. We can (and should) use the name ‘db’ since this is the name of the service we defined and linked to earlier, and the port is 3306 and not 32000 since this code is not running on the host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the app
&lt;/h2&gt;

&lt;p&gt;In order to run the our dockerized app, we will execute the following command from the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see the image being built, the packages installed according to the requirements.txt, etc. If everything went right, you will see the following line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;app_1  |  &lt;span class="k"&gt;*&lt;/span&gt; Running on http://0.0.0.0:5000/ &lt;span class="o"&gt;(&lt;/span&gt;Press CTRL+C to quit&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can find out that everything is running as expected by typing this url in a browser or using curl, and receiving the following response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"favorite_colors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="nl"&gt;"Lancelot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blue"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"Galahad"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yellow"&lt;/span&gt;&lt;span class="p"&gt;}]}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access the database directly using the mysql client and following command (make sure your client is the same version of MySQL specified in the docker-compose.yml):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;mysql &lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;127.0.0.1 &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;32000 &lt;span class="nt"&gt;-u&lt;/span&gt; root &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is a must to specify the host IP, since &lt;a href="https://dev.mysql.com/doc/refman/5.7/en/connecting.html" rel="noopener noreferrer"&gt;when the default ‘localhost’ is used MySQL ignores the port parameter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have learned how to dockerize a simple Flask-MySQL using docker-compose. Now this app can be used without tiresome preconfiguration on every host with Docker and docker-compose, and is encapsulated from the host environment!&lt;/p&gt;

</description>
      <category>python</category>
      <category>docker</category>
      <category>mysql</category>
      <category>flask</category>
    </item>
  </channel>
</rss>
