<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Florian Dahlitz on Medium]]></title>
        <description><![CDATA[Stories by Florian Dahlitz on Medium]]></description>
        <link>https://medium.com/@DahlitzF?source=rss-7aee34c55666------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*jskski1Ljnz0w6Luo3nsOA.jpeg</url>
            <title>Stories by Florian Dahlitz on Medium</title>
            <link>https://medium.com/@DahlitzF?source=rss-7aee34c55666------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 07 Apr 2026 00:57:13 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@DahlitzF/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[How To Modularise Your Shell Config]]></title>
            <link>https://medium.com/@DahlitzF/how-to-modularise-your-shell-config-81581ca8da?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/81581ca8da</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[shell]]></category>
            <category><![CDATA[linux]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[unix]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Wed, 13 Nov 2019 10:52:58 GMT</pubDate>
            <atom:updated>2019-11-13T10:52:58.118Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fZ3Ab-5apTeAnW7CG5HhWQ.png" /></figure><p>Modularising your shell config for a cleaner setup</p><p><strong>Note:</strong> The setup described in the following sections can be applied to shells like <em>bash</em>, <em>zsh, fish </em>and other common unix shells. However, keep in mind that the command(s) <em>might</em> differ a bit.</p><p>I’m using custom shell commands, aliases, and functions quite heavily. As my .bashrc and .zshrc grew too big, I decided to mudularise my config and want to share with you how I’ve done it.</p><p>First of all, I’ve created a dedicated directory in my root directory for all of my custom shell commands, aliases, and functions:</p><pre>$ mkdir ~/.shell_config</pre><p>Inside of the directory I created dedicated files per topic. My current .shell_config directory looks like this:</p><pre>$ tree ~/.shell_config<br>/home/florian/.shell_config<br>├── application_aliases<br>├── directory_aliases<br>├── enhanced_shell_commands<br>└── git_aliases</pre><pre>0 directories, 4 files</pre><p>The definition of one of these files is pretty straightforward:</p><pre>$ cat ~/.shell_config/application_aliases<br>alias python3.9=&quot;/home/florian/workspace/python/cpython/python&quot;<br>alias python=&quot;python3.8&quot;<br>alias open=&quot;xdg-open&quot;</pre><pre>alias build_latest_python=&quot;cd /home/florian/workspace/python/cpython &amp;&amp; git pull &amp;&amp; make &amp;&amp; make test&quot;</pre><pre>function pycharm() {<br>    /usr/local/bin/pycharm-2019.2.3/bin/pycharm.sh &quot;$1&quot; &lt;/dev/null &amp;&gt;/dev/null &amp;<br>}</pre><p>Finally, add the following line to your .bashrc , .zshrc or whatever your shell config file is called to automatically load all files inside the .shell_config directory:</p><pre>for f in ~/.shell_config/*; do source $f; done</pre><p>And that’s it! Congratulations, you’ve modularised your shell config! If you want to get a list of useful unix commands, aliases and functions I’m currently using, visit my <a href="https://github.com/DahlitzFlorian/useful-unix">useful-unix</a> repository over at GitHub. Stay curious and keep coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=81581ca8da" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Use OBS Studio Under Debian]]></title>
            <link>https://medium.com/@DahlitzF/how-to-use-obs-studio-under-debian-8c7dbbe333e5?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/8c7dbbe333e5</guid>
            <category><![CDATA[open-broadcaster-software]]></category>
            <category><![CDATA[obs]]></category>
            <category><![CDATA[recording-studios]]></category>
            <category><![CDATA[recording]]></category>
            <category><![CDATA[debian]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Fri, 25 Oct 2019 18:15:24 GMT</pubDate>
            <atom:updated>2019-10-25T18:16:17.000Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kLWypvYdOBh5YaT3zxHiMw.jpeg" /></figure><p>Solving the black screen <em>Screen Capture (XSHM)</em> issue occurring under Debian</p><p>Recently, I wanted to use OBS Studio (Open Broadcast Software) to record some of my coding sessions. As I switched from Windows to Debian a lot of things are still new to me.</p><p>As I followed along there <a href="https://obsproject.com/wiki/install-instructions#debian-installation-unofficial">(unofficial) build instructions</a>, I got OBS Studio up and running except the most important feature: Screen Capture.</p><p>That’s why I also tried building it from source and installing it via snap. However, audio and Window Capture just worked fine, but the Screen Capture did not.</p><p>It seemed to be a display server related problem (Again, I’m fairly new to Linux), that’s why I specifically searched for terms I already came across during my search: Wayland and X11.</p><p>After reading a few user reports I conclude, that OBS is not working well together with Wayland. In fact, you won’t get OBS running properly on operating systems using Wayland as a display server protocol. However, most users revealed, that using X server helps.</p><p>The loginctl command showed me, which type of display server protocol I was using: Wayland.</p><p>A bit of researched revealed, that I simply needed to uncomment a single line in a configuration file to force my Debian system to use X11, which is already installed, instead of Wayland.</p><p>Simply go to /etc/gdm3/daemon.conf and uncomment the line containing WaylandEnable (at my system it was line 7) so it looks like this:</p><pre># GDM configuration storage<br>#<br># See /usr/share/gdm/gdm.schemas for a list of available options.</pre><pre>[daemon]<br># Uncomment the line below to force the login screen to use Xorg<br>WaylandEnable=false</pre><pre># Enabling automatic login<br>#  AutomaticLoginEnable = true<br>#  AutomaticLogin = user1</pre><pre># Enabling timed login<br>#  TimedLoginEnable = true<br>#  TimedLogin = user1<br>#  TimedLoginDelay = 10</pre><pre>[security]</pre><pre>[xdmcp]</pre><pre>[chooser]</pre><pre>[debug]<br># Uncomment the line below to turn on debugging<br># More verbose logs<br># Additionally lets the X server dump core if it crashes<br>#Enable=true</pre><p><strong>Note:</strong> Depending on your setup the directory might be /etc/gdm/ and the configuration files name might be different as well. Please also keep in mind, that you need to reboot your system before changes take effect.</p><p>I hope this short article helps you on your own setup — keep coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8c7dbbe333e5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Create Your Own Timing Context Manager In Python]]></title>
            <link>https://medium.com/@DahlitzF/how-to-create-your-own-timing-context-manager-in-python-a0e944b48cf8?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/a0e944b48cf8</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Fri, 26 Apr 2019 16:49:56 GMT</pubDate>
            <atom:updated>2019-04-26T16:56:10.958Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UZAHZ7GvucYj1KFHSiPEpw.jpeg" /></figure><p>After publishing my last article, which was about <a href="https://blog.usejournal.com/list-sort-vs-sorted-list-aab92c00e17">list.sort() and sorted(list)</a>, I was asked, why I was using the <a href="https://github.com/DIYer22/boxx">boxx</a> library instead of built-in functionalities to measure the execution time of certain pieces of code. I responded, that it’s only personal preference and that you can simply create your own context manager measuring the execution time of code pieces.</p><p>In this article I will show you how to create your own timing context manager. Furthermore, different ways to accomplish that are covered.</p><h3>Time Measurement</h3><h4>What’s already available?</h4><p>Python provides you different ways to measure the execution time. For instance you can use Python’s built-in <a href="https://docs.python.org/3.7/library/timeit.html">timeit module</a> to measure the execution time of small pieces of code.</p><pre>&gt;&gt;&gt; import timeit<br>&gt;&gt;&gt; timeit.timeit(&#39;&quot;-&quot;.join(str(n) for n in range(100))&#39;, number=10000)<br>0.3018611848820001</pre><p>However, the timeit.timeit function only accepts strings. This can be quite annoying if you want to measure larger functions. The following example is from the official <a href="https://docs.python.org/3.7/library/timeit.html#examples">Python documentation</a> and shows you, how you can run and measure functions using the timeit module.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a59a6c5a7324886f0be26d2f582dc3ec/href">https://medium.com/media/a59a6c5a7324886f0be26d2f582dc3ec/href</a></iframe><p>Although it works, it does not look really <em>pythonic</em>.</p><p>Another way to measure the execution time is to make use of Python’s built-in <a href="https://docs.python.org/3/library/profile.html">cProfile module</a>. However, this is <strong>not</strong> recommended! It’ s simply a workaround to get a sense of how long certain code pieces need to be executed. In fact it’s not really precise. You can use it via:</p><pre>&gt;&gt;&gt; python -m cProfile &lt;file_name.py&gt;</pre><p>Now that we have seen a recommended but unpythonic, and a discredited and unpythonic way, how can we implement our own recommended and pythonic solution?</p><h4>The Idea</h4><p>The idea is quite simple: We take the time at the beginning of the execution and subtract it from the time at the end of the execution. Fortunately, Python has a built-in module we can use: time .</p><pre>&gt;&gt;&gt; import time<br>&gt;&gt;&gt; start = time.time()<br>&gt;&gt;&gt; # do some stuff<br>&gt;&gt;&gt; end = time.time()<br>&gt;&gt;&gt; print(f&quot;Elapsed Time: {end - start}&quot;)</pre><p>Great! However, adding one line of code before and two lines after a code piece we want to measure is an overhead I don’t want to have. So let’s create a context manager for that.</p><h3>Creating A Context Manager</h3><p>There exist different ways to create a context manager in Python. We will have a look at two ways to accomplish that: A class-based and a generator-based context manager.</p><h4>Class-based Context Manager</h4><p>To create a class-based context manager, the dunder methods __enter__ and __exit__ need to be implemented. The first one is called when entering a context (manager), the latter is called when leaving the context.</p><p>With this knowledge we can create a Timer class implementing both methods. When entering the context, we want to get the current time and save it to a start instance variable. If we leave the context, we want to get the current time and subtract the start time from it. The result is printed.</p><p>To customize the output, we let the user specify a description, which is printed before the elapsed time. The following gist shows you the ready-to-use class.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/729eb4025665563ef91ae93f0030fc5b/href">https://medium.com/media/729eb4025665563ef91ae93f0030fc5b/href</a></iframe><h4>Generator-based Context Manager</h4><p>The generator-based approach is a bit more straightforward. Basically, we create a generator function containing the program flow (taking start and end time as well as printing the elapsed time). The @contextmanager decorator turns the generator function into a proper context manager by wrapping the generator by the GeneratorContextManager object.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bcc37ae40ddfaf94c26d6d781800dfdc/href">https://medium.com/media/bcc37ae40ddfaf94c26d6d781800dfdc/href</a></iframe><p>Let’s describe it a bit less formal: What happens is, that entering the context (timing) results in taking the current time and <em>playing the ball back to the code inside the context using </em><em>yield . </em>If the code inside of the with -block is executed, we jump back to the point right after the yield keyword. Now we calculate the elapsed time and print it. We are now leaving the context.</p><h3>Summary</h3><p>In this article you learned how to create your own timing context manager. After creating the basic concept, you implemented the context manager in two ways: Class-based and generator-based. The resulting class and generator function are ready-to-use.</p><p>I hope you enjoyed reading this article and learned something new. Feel free to share this article with your friends and let me know what you think about the discussed approaches in the comments. Stay curious and keep coding!</p><h3>References</h3><p><a href="https://book.pythontips.com/en/latest/context_managers.html">https://book.pythontips.com/en/latest/context_managers.html</a><br><a href="https://docs.python.org/3/library/contextlib.html">https://docs.python.org/3/library/contextlib.html</a></p><figure><a href="https://usejournal.com/?utm_source=medium.com&amp;utm_medium=noteworthy_blog&amp;utm_campaign=guest_post_image"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f2IVAl0TbsfES9cFGYr40g.png" /></a></figure><p>📝 Read this story later in <a href="https://usejournal.com/?utm_source=medium.com&amp;utm_medium=noteworthy_blog&amp;utm_campaign=guest_post_read_later_text">Journal</a>.</p><p>🗞 Wake up every Sunday morning to the week’s most noteworthy Tech stories, opinions, and news waiting in your inbox: <a href="https://usejournal.com/newsletter/?utm_source=medium.com&amp;utm_medium=noteworthy_blog&amp;utm_campaign=guest_post_text">Get the noteworthy newsletter &gt;</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a0e944b48cf8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[list.sort() vs. sorted(list)]]></title>
            <link>https://medium.com/@DahlitzF/list-sort-vs-sorted-list-aab92c00e17?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/aab92c00e17</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Mon, 08 Apr 2019 11:52:37 GMT</pubDate>
            <atom:updated>2020-01-09T19:16:08.655Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/870/1*e1TZG3Oa-mzKIhdcom7hFg.png" /></figure><h4>A closer look at Python’s built-in List Sorting Methods concerning Memory Consumption and Time Efficiency</h4><h4>Introduction</h4><p>Recently, I came across the question, which method to sort a list is more efficient: Using Python’s built-in sorted function or relying on the list.sort method. To answer this question I started a little investigation described in this article. You can find the repository I’m referring to on <a href="https://github.com/DahlitzFlorian/list-sort-vs-sorted-list">GitHub</a>.</p><p>The starting point is a Python list containing 1.000.000 random numbers (integers) built using the random module:</p><pre>import random</pre><pre>arr = [random.randint(0, 50) for r in range(1_000_000)]</pre><p>The generated numbers are in the range from 0 (inclusive) to 50 (inclusive).</p><h4>Memory Consumption</h4><p>Let’s have a look at the memory consumption of both functions. Therefore, we are using the builtin resource module to track the maximum memory usage. As the resource module enables us to track the memory usage of a single thread, we are running the sorting of our list in a separate thread. You can use the FunctionSniffingClass included in the <a href="https://github.com/DahlitzFlorian/list-sort-vs-sorted-list">repository</a> to do so.</p><p>Let’s have a closer look at our Python script:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fda01eda63091033123094c816e85fee/href">https://medium.com/media/fda01eda63091033123094c816e85fee/href</a></iframe><p>We create two wrapper functions for the built-in ones to be able to pass them as arguments to the FunctionSniffingClass . We could pass the built-in sorted function directly to the FunctionSniffingClass , but we want the same chances for both built-ins. Furthermore, some simple command-line argument parsing is implemented to be able to use it as simple as possible from the command-line.</p><p>Curious how both built-ins perform? Let’s see!</p><pre>$ python memory_measurement/main.py sort<br>Calling the Target Function...<br>Function Call Complete<br><br>MAX Memory Usage: 23.371 MB</pre><pre>$ python memory_measurement/main.py sorted<br>Calling the Target Function...<br>Function Call Complete<br><br>MAX Memory Usage: 30.879 MB</pre><p>As you can see, the sorted function consumed around 32% more memory as the list.sort method. This was predictable as the latter on modifies the list in-place, whereas the first ones is always creating a separate list.</p><h4>Speed</h4><p>To be able to time the execution time of both wrapper functions, we make use of the third-party <a href="https://github.com/DIYer22/boxx">boxx</a> module. The following gist shows you how we can make use of its timeit function to time the execution time of both functions.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e2502ed33473b7153d49e1e871a3b1b6/href">https://medium.com/media/e2502ed33473b7153d49e1e871a3b1b6/href</a></iframe><p><strong>Note:</strong> Be sure to run the sorted_builtin function first as the list.sort method sorts the list just in-place, so the sorted function wouldn’t have to sort anything!</p><p>Running the above snippet prints the following output:</p><pre>$ python main.py<br>&quot;sorted(list)&quot; spend time: 0.1104379<br>&quot;list.sort()&quot; spend time: 0.0956471</pre><p>As you can see, the list.sort method is slightly faster than the sorted function. Why is this the case? Let’s disassemble both functions and see, whether we can conclude the answer based on the bytecode:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/863/1*DJLJc_rE7TqrJ9Re34pydw.png" /><figcaption>Disassembled list.sort()</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/757/1*GbRpCzq5pLSwPOv0PeJ4KQ.png" /><figcaption>Disassembled sorted(list)</figcaption></figure><p>Both functions bytecode is pretty much the same. The only difference is, that the list_sort function first loads the list, loads the method (sort) followed by calling the method on the list without any arguments, whereas the the sorted_builtin function first loads the built-in sorted function, followed by loading the list and calling the loaded function with the list as argument.</p><p>Additionally, both use the same sorting algorithm: <a href="https://en.wikipedia.org/wiki/Timsort">Timsort</a>. So if both are using the same sorting algorithm and the bytecode of both is pretty much the same, why are the timing results different?</p><p>My guess is, that as list.sort can work with a known size, and swap elements within that size, whereas sorted has to work with an unknown size. Therefore, the new list created by sorted needs to be resized if not enough memory is left when appending a new element. And this takes time!</p><p>Having a look at the CPython source code, we find the following comment about resizing list objects:</p><blockquote>The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, …<br>- CPython: Objects/listobject.c</blockquote><p>If we bring back to mind, that we are dealing with a list of size 1.000.000, we can see: that’s a lot of resizing! Unfortunately, this is the best answer we get, when asking why list.sort is 13% faster than sorted .</p><p>Unfortunately my guess is wrong. As <a href="https://twitter.com/ncoghlan_dev">Nick Coghlan,</a> one of the CPython core developer, stated on Twitter, the size of the resulting list is known. Basically, the following is happening:</p><pre>new_array = arr.copy()<br>new_array.sort()</pre><h3>Nick Coghlan on Twitter</h3><p>@anthonypjshaw @DahlitzF This theory is not correct - sorted knows how big the input is in this case, so it can preallocate the output. What it can&#39;t avoid is the extra data copying required to make a whole new list - if you measure &quot;arr2 = arr.copy(); arr2.sort()&quot; it should be comparable to sorted(arr).</p><p>However, he also states, that it’s not really obvious if you don’t know that it’s there and look explicitly for in the <a href="https://github.com/python/cpython/blob/2fb2bc81c3f40d73945c6102569495140e1182c7/Python/bltinmodule.c#L2238">implementation</a>.</p><h3>Nick Coghlan on Twitter</h3><p>@anthonypjshaw @DahlitzF The resizing idea was a decent guess though - even when you go read the source code, the preallocation trick is buried way down in the list.extend implementation, and hence is easy to miss if you don&#39;t already know it is there :)</p><p>This implementation results in the execution time difference as creating a copy of the list takes some time.</p><h4>Additional Remarks</h4><p>Before wrapping up this article, let’s have a look at what the official Python documentation says about this topic.</p><blockquote>You can also use the <a href="https://docs.python.org/3/library/stdtypes.html#list.sort">list.sort()</a> method. It modifies the list in-place (and returns None to avoid confusion). Usually it’s less convenient than <a href="https://docs.python.org/3/library/functions.html#sorted">sorted()</a> - but if you don’t need the original list, it’s slightly more efficient.<br> — <a href="https://docs.python.org/3/howto/sorting.html#sorting-basics">Sorting HOW TO</a></blockquote><p>As you can see, the official documentation states, what we have already proven: list.sort is slightly more efficient. Furthermore, it tells us, that sorted is usually more convenient.</p><p>Another question that my arise is, whether both sorting techniques are stable. Fortunately, the docs have an answer to that:</p><blockquote>Sorts are guaranteed to be <a href="https://en.wikipedia.org/wiki/Sorting_algorithm#Stability">stable</a>. That means that when multiple records have the same key, their original order is preserved.<br> — <a href="https://docs.python.org/3/howto/sorting.html#sort-stability-and-complex-sorts">Sorting HOW TO</a></blockquote><p>This is also true, when using the <em>reverse</em> parameter or applying the reversed function twice.</p><h4>Conclusion</h4><p>The previous investigations showed us, that list.sort is slightly faster than sorted and consumes around 24% less memory. However, keep in mind that list.sort is only implemented for lists, whereas sorted accepts any iterable. Furthermore, if you use list.sort, you will lose your original list.</p><p>I hope this article revealed you more insights into the Python programming language. Stay curious and keep coding!</p><figure><a href="https://usejournal.com/?utm_source=medium.com&amp;utm_medium=noteworthy_blog&amp;utm_campaign=tech&amp;utm_content=guest_post_image"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PYxBP_WV7LI6zc-zdUkNqQ.png" /></a></figure><p>📝 Read this story later in <a href="https://usejournal.com/?utm_source=medium.com&amp;utm_medium=noteworthy_blog&amp;utm_campaign=tech&amp;utm_content=guest_post_read_later_text">Journal</a>.</p><p>👩‍💻 Wake up every Sunday morning to the week’s most noteworthy stories in Tech waiting in your inbox. <a href="https://usejournal.com/newsletter/noteworthy-in-tech/?utm_source=medium.com&amp;utm_medium=noteworthy_blog&amp;utm_campaign=tech&amp;utm_content=guest_post_text">Read the Noteworthy in Tech newsletter</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=aab92c00e17" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Run Python Applications as non-root user in Docker Containers — by example]]></title>
            <link>https://medium.com/@DahlitzF/run-python-applications-as-non-root-user-in-docker-containers-by-example-cba46a0ff384?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/cba46a0ff384</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Sat, 23 Mar 2019 19:33:05 GMT</pubDate>
            <atom:updated>2019-03-23T19:33:05.980Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MPTh_FBx_Dy_AOqhnxV0jQ.jpeg" /></figure><h3>Run Python Applications as non-root user in Docker Containers — by example</h3><p><em>After the emersion of the </em><a href="https://www.sdxcentral.com/articles/news/kubernetes-docker-containerd-impacted-by-runc-container-runtime-bug/2019/02/"><em>runC container runtime bug</em></a><em> it’s finally the time to run processes in Docker containers as non-root user. This article shows you how to achieve that with your Python applications.</em></p><h4>Using requirements.txt</h4><p>If your project uses a plain requirements.txt , you can use the following snippet to run your application as non-root process in the Docker container.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e7e5b6a6f8b0af4a30740dcc12f481dc/href">https://medium.com/media/e7e5b6a6f8b0af4a30740dcc12f481dc/href</a></iframe><p>pip is upgraded before using a worker user, because it’s installed as root and can’t be accessed by a non-root user. After switching the current user to the worker user every COPY instruction needs the --chown=&lt;user&gt;:&lt;group&gt; flag to signal to change the file or directory owner to the worker user (it’s root by default).</p><p>Running pip install with the --user flag installs the dependencies <em>for</em> the current user in the .local/bin directory in the users home directory. Therefore, we need to add this newly created directory to the PATH environment variable.</p><h4>Using Pipenv</h4><p>As many projects use Pipenv to handle their dependencies, here’s a way to run your Python applications, which depend on Pipenv, as non-root process in a Docker container.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/226c92954ac2eefdaa84d2ba66a9f1c1/href">https://medium.com/media/226c92954ac2eefdaa84d2ba66a9f1c1/href</a></iframe><p>This one is very similar to the previous one. Notice that the .local/bin directory is added to the PATH environment variable right after Pipenv is installed. As Pipenv itself is installed with the --user flag, it’s installed inside the .local/bin directory. To make use of it in line 14, it has to be added to PATH .</p><h4>Conclusion</h4><p>I hope this short article helps you running your Python applications safely as non-root user in a Docker container. If there are any questions, feel free to leave a comment or contact me via <a href="https://twitter.com/DahlitzF">Twitter</a>. Make sure to share it with your friends if you think it’s a helpful article. Thanks for reading, stay curious and keep coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cba46a0ff384" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Customize Click Help Page]]></title>
            <link>https://medium.com/@DahlitzF/customize-click-help-page-e302a6758d09?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/e302a6758d09</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python-programming]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Tue, 01 Jan 2019 18:37:26 GMT</pubDate>
            <atom:updated>2019-01-01T18:37:26.214Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wDqDk71ItB0KONfN4DnY2w.jpeg" /></figure><p>Recently, I wanted to start my open source journey by contributing to an open source project called <a href="https://github.com/tonybaloney/wily">wily</a>. The issue I was working on was to first add a version flag to print the current version of the tool and second to add the version to the help page.</p><p>As the project uses <a href="https://click.palletsprojects.com/en/7.x/">click</a> to create a user friendly command-line interface, the help page is auto-generated based on the docstrings. That’s great, but refuses to inject custom dynamic texts. To recall the example of adding the version to the help page, you need to update your version twice: Inside of the <em>__init__.py </em>and inside of the docstring of the main cli command. But you don’t want to change the version of the tool at two places. So, how can you dynamically inject it into the docstring?</p><p>A quick research about functions docstrings reveals, that you can access and modify them using function_name.__doc__ . Problem: You can’t do it inside of the function itself as the docstring is added after function creation. Solution: Modify the docstring afterwards. And to anticipate decorators are great for that!</p><p>So, let’s demonstrate that by an example project. Consider the following project structure:</p><pre>└── tool<br>    ├── __init__.py<br>    ├── __main__.py<br>    └── custom_decorators.py</pre><p><em>tool</em> is our tools directory, the <em>__main__.py</em> will include the logic of the command-line tool and <em>custom_decorators.py</em> contains our decorator, which we will use later to change the help page.</p><p>Let’s start by having a look at the <em>__init__.py</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e2ebbb4c533e4cfe4cae2115eb340cd5/href">https://medium.com/media/e2ebbb4c533e4cfe4cae2115eb340cd5/href</a></iframe><p>As you can see, it only contains the __version__ of the tool. Next, we will have a look at the <em>__main__.py</em>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a06e6f5c90d49ee3ba3a9933f3d13175/href">https://medium.com/media/a06e6f5c90d49ee3ba3a9933f3d13175/href</a></iframe><p>It’s just a very basic command-line tool created with click. If you are not very familiar with the code, check out the <a href="https://click.palletsprojects.com/en/7.x/">documentation</a>. You are able to print the version using tool --version and print some text using the do command:</p><pre>$ python tool/__main__.py do &quot;Some Text&quot;</pre><p>As already mentioned, you are able to display the help page using --help natively, which is generated based on the docstrings. Let’s modify the help page a little bit! Therefore, we will add the tools version to the help pages heading.</p><p>First of all, we need a custom decorator modifying the __doc__ attribute of the cli function, which is our main method or group in this case. Let’s call the decorator add_version and put the corresponding code into <em>tool/custom_decorators.py</em>. The code is pretty straightforward:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/088256e58c0fd81724167284dcf10958/href">https://medium.com/media/088256e58c0fd81724167284dcf10958/href</a></iframe><p>Now, we only need to add the decorator to our cli function before all other click decorators are applied:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8e6906582bf79d96ea8195bbd773e485/href">https://medium.com/media/8e6906582bf79d96ea8195bbd773e485/href</a></iframe><p>That’s it! We changed the auto-generated help page and injected the tools version using a custom decorator. The whole project can be found on <a href="https://github.com/DahlitzFlorian/modify-click-help-page">GitHub</a>. Feel free to get it running on your own machine, to extend it further and to share it!</p><p>If you liked it, clap for the story. Feel free to leave comments and share it with others. Thanks for reading, stay curious and keep coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e302a6758d09" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Python’s f-strings vs. str()]]></title>
            <link>https://medium.com/@DahlitzF/pythons-f-strings-vs-str-e22995cefef6?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/e22995cefef6</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[python-programming]]></category>
            <category><![CDATA[python3]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Wed, 26 Dec 2018 15:31:48 GMT</pubDate>
            <atom:updated>2018-12-26T15:31:48.300Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pfHYR63tq0TRw1_JYWF_PA.png" /></figure><p>A few months ago I’ve seen a tweet from a Python learner with a code snippet containing f-strings. I asked, why she’s not using format() . She answered, that this is the new way of formatting strings. I was curious about it as I didn’t hear about it before. Seeing other people using it, I started to do it as well.</p><p>Two weeks ago I spotted a Pull Request on GitHub where somebody used f-strings to convert a value to a string as in the example below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7917fbca743169e4708939621cf5fc0c/href">https://medium.com/media/7917fbca743169e4708939621cf5fc0c/href</a></iframe><p>I was surprised by the usage of f-strings in this particular case. Another user commented to use str() instead. This conversation led me to the question, which one of both is faster as it was a computationally intensive piece of code.</p><p>Using boxx.timeit showed me the not irrelevant time difference.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4002e56d93c7cb7e489fd5488aa33d17/href">https://medium.com/media/4002e56d93c7cb7e489fd5488aa33d17/href</a></iframe><p><strong>“f-strings” spend time: 0.08900404<br>&quot;str” spend time: 0.160588</strong></p><p>Wondering why this is the case? Looking at the byte code gives us the answer. Python provides a module for such cases, the <em>Disassemble</em>-Module. Let’s have a closer look at what’s happening.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9308db97ec537321a3b545b9758c49b6/href">https://medium.com/media/9308db97ec537321a3b545b9758c49b6/href</a></iframe><p>The result is shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qItzxegBHoJy4obEmEBcZw.png" /></figure><p>As you can see the str_string method consists of one more command (CALL_FUNCTION). Function calls are expensive and f-strings don’t need to call a separate function.</p><p>To summarize f-strings are faster than str() in terms of converting integers and such types to string. But keep in mind, that we only had a look at simple types. How they perform on more complex types is currently out of my knowledge as I didn’t test it.</p><p>Feel free to leave a comment with your own thoughts. Stay curious and keep coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e22995cefef6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[#16 and #17 Week of the Year]]></title>
            <link>https://medium.com/coding-experiences/16-and-17-week-of-the-year-798465ae2d?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/798465ae2d</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[learning]]></category>
            <category><![CDATA[100daysofcode]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Sun, 29 Apr 2018 14:49:37 GMT</pubDate>
            <atom:updated>2018-04-29T14:49:37.160Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ICBT-jxfLVgpCO80d897fw.jpeg" /></figure><p><em>Ending up the #100DaysOfCode-challenge with informing about newer Python releases, asynchronous programming and community work.</em></p><p>With this article I not only summarise my past two weeks of learning and coding, but also end up my #100DaysOfCode-challenge. Two weeks ago I had ten days left before finishing the challenge and decided to spread them over two weeks to have some more time to get into Python a little deeper.</p><h4>More insights into Python</h4><p>The past two weeks I spent more on getting deeper into Python itself than working on a specific project like my personal portfolio page. Therefore, I read different PEPs at the official Python page as well as followed the <a href="https://pymotw.com"><em>Python Model Of The Week</em></a> (PyMOTW). I tested the <em>sched</em>-package providing great resources for schedulers, and the <em>linecache</em>-package. Additionally, I traversed GitHub searching for interesting Python projects to contribute to.</p><p>At some point I helped a fellow student refactoring his own codebase and applying PEP 8 to it, so that he has it easier to contribute to others projects in the future or that others can contribute to his projects easier.</p><p>Besides the previous mentioned things I also spent time on getting my portfolio page done. Unfortunately, I’m not finished yet — still struggling with getting the first things running on an Ubuntu server. This will be the project I will focus on in the next weeks.</p><p>Furthermore, I kept reading <strong>Python Tricks </strong>from <a href="https://twitter.com/dbader_org">Dan Bader</a>, which made me become a more pythonic coder. I can really recommend this book to everybody, who’s interested in Python!</p><p>Additionally, I made some more community work than before helping others to find a solution for their problems. Therefore, I read issues at GitHub projects I worked with and provided my own solutions if necessary.</p><p>Last but not least I worked with asynchronous-package like <em>asyncio</em> and <em>tornado</em>. The whole topic asynchronous programming is really powerful and interesting, so I will keep an eye on that.</p><p>After all I have to admit, that the past challenge was sometimes very easy and sometime really challenging. It was a great experience to finish the second round of it and I can only recommend to everybody to do it on it’s own.</p><p>I won’t update this blog weekly as I did during the challenge, but I will post updates once in a while and maybe some more articles on “How to …” do something.</p><p>Thanks for the great support during the challenge and for reading this, stay curious and keep coding!</p><h4>Articles and Podcast Episodes</h4><p>Providing a list of great articles I’ve read over the past week and podcast episodes I’ve listened to got a natural part of my weeklies summary. Here are the lists for the past two weeks.</p><h4>Articles</h4><ul><li><a href="https://hackernoon.com/asynchronous-python-45df84b82434">Asynchronous Python — Await the Future</a></li><li><a href="https://docs.python.org/3/whatsnew/3.6.html#what-s-new-in-python-3-6">What’s New In Python 3.6</a> (with the focus on PEP 530)</li></ul><p><strong>Podcast Episodes</strong></p><ul><li><a href="https://itunes.apple.com/gb/podcast/importance-transparency-user-control-in-machine-learning/id944929220?i=1000408741886&amp;mt=2">The importance of transparency and user control in machine learning</a> — O’Reilly Data Show</li><li><a href="https://itunes.apple.com/gb/podcast/158-quantum-computing-and-python/id979020229?i=1000409434389&amp;mt=2#">#158 Quantum Computing and Python</a> — Talk Python To Me</li><li><a href="https://itunes.apple.com/gb/podcast/74-contributing-to-open-source-effectively/id1173690032?i=1000409293549&amp;mt=2">#74 Contributing to Open Source effectively</a> — Python Bytes</li><li><a href="https://itunes.apple.com/gb/podcast/how-language-shapes-the-way-we-think-lera-boroditsky/id160904630?i=1000408678003&amp;mt=2#">How language shapes the way we think | Lera Boroditsky</a>— TED Talks Daily</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=798465ae2d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/coding-experiences/16-and-17-week-of-the-year-798465ae2d">#16 and #17 Week of the Year</a> was originally published in <a href="https://medium.com/coding-experiences">Coding experiences</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[#15 Week of the Year]]></title>
            <link>https://medium.com/coding-experiences/15-week-of-the-year-6a22387a44c7?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/6a22387a44c7</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[blogger]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Sun, 15 Apr 2018 15:59:44 GMT</pubDate>
            <atom:updated>2018-04-15T15:59:44.165Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*m7mCbuEL0NEfqlSoZ9COAg.jpeg" /><figcaption>A simple face recognition application based on a predefined model.</figcaption></figure><p><em>A week on the subject of image recognition and Python secrets everybody should know about.</em></p><h4>Image and Video Recognition</h4><p>This week I started with the focus on learning more about image recognition with a predefined model instead of a neural network. I already worked with OpenCV manipulating existing images and created a package for <a href="https://github.com/DahlitzFlorian/python-color-changer">colour manipulation</a>.</p><p>To keep things simple I searched for a predefined model, which would detect faces in an image if implemented correctly. I found a useful set of cascade classifiers and imported the one for face recognition. After that I made use of OpenCV’s multi-scale detection method <em>detectMultiScale()</em> to find all matching objects in a given image. Furthermore, I unpacked the results and drew red rectangles around the found coordinates marking the faces. One of the test results is shown in the thumbnail.</p><p>So far so good. But what about recognising faces and objects in videos? This seemed more powerful and interesting to me, so I started to find out, how to launch the webcam of my laptop, make a short video and to the same thing with every collected image as in the example before.</p><p>Luckily, OpenCV provides build-in functionalities for that as well. Turning one the webcam and collecting images as long as the user wants was very quite easy. Now the more difficult part impended: Recognising single objects in a series of images.</p><p>To solve the problem I set the first made image as my basic background frame. Every image collected afterwards was compared to the first one. This was done by simply calculating the difference between each frame. The result of the subtraction was a new frame. Applying certain thresholds to it created a black-white frame with new appearing objects in white and everything else in black. With the received coordinates of the new appearing objects I was able to draw a red rectangle around them and hence to mark moving objects.</p><p>The motion detection application is not perfect right now due to mis-detection of certain objects and under changing light conditions. But it was a great first try on this topic.</p><h4>Python’s ABC-package</h4><p>However, I did not only worked on image and video recognition, though. I made a quick excursion into Python’s object-oriented fields. Doing so, I came across the Abstract Base Class-package (ABC) providing great decorators for ensuring correct class implementations and inheritance.</p><p>Because code speaks more than words, I show you the beauty of the ABC-package in three pictures:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n0G6grjp6WXzTHFuLYDgSw.jpeg" /></figure><p>The above picture shows you, that with the correct implementation of ABC you are not able to run an application if an important method (in this case <em>bar()</em>) is missing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w9a480Jy8BN8HV_w5nNSqA.jpeg" /></figure><p>This picture illustrates, that it’s not possible to instantiate the base class, which is quite helpful in many cases. In many applications and frameworks base classes shouldn’t be instantiated. Only concrete classes inheriting from the base class.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s4rUcLIzNIF9sj-xr8Q21g.jpeg" /></figure><p>The last picture shows a working implementation with a base class and an instantiation of the concrete class.</p><p>Additionally, I learned about <em>shallow</em> and <em>deep</em> copies of objects and how to create them using Python’s <em>copy</em>-package. You should definitely check it out.</p><h4>Additional Information</h4><p>Besides the mentioned topics, I kept working on my personal portfolio page, listened to several podcast episodes and learned about Python’s __str__() and __repr__() dunder methods.</p><p>Summarising the past week I have to admit, that it was only another “light” week of coding. University stuff keeps me busy, but nevertheless I try to code everyday until the end of the #100DaysOfCode-challenge. Staying curious and keeping coding as always is a passion, that needs to be lived!</p><h4>Articles and Podcast Episodes</h4><p>As usual I share podcast episodes I listened to and articles I read over the past week and which are worth sharing.</p><p><strong>Articles</strong></p><ul><li><a href="http://omz-software.com/pythonista/">Pythonista 3 - A Full Python IDE for iOS</a></li><li><a href="https://github.com/cclauss/Ten-lines-or-less">Ten-lines-or-less — Python scripts that are short but useful or interesting</a></li><li><a href="https://medium.com/thrive-global/how-to-maximize-the-first-90-minutes-of-your-day-b65158a40222">How To Get Life-Changing Clarity Within 90 Minutes Of Waking Up</a></li></ul><p><strong>Episodes</strong></p><ul><li><a href="https://itunes.apple.com/gb/podcast/39-thorough-software-testing-for-critical-features/id1029487211?i=1000407754956&amp;mt=2">39: Thorough software testing for critical features</a> — Test and Code</li><li><a href="https://itunes.apple.com/gb/podcast/37-what-tests-to-write-first/id1029487211?i=1000405509605&amp;mt=2">37: What tests to write first</a> — Test and Code</li><li><a href="https://itunes.apple.com/gb/podcast/73-this-podcast-comes-in-any-color-you-want-as-long/id1173690032?i=1000408794377&amp;mt=2">This podcast comes in any color you want, as long as it’s black</a> — Python Bytes</li><li><a href="https://itunes.apple.com/gb/podcast/292-elasticsearch-doubling-down-on-open-philipp-krenn/id341623264?i=1000408656074&amp;mt=2">292: Elasticsearch and doubling down on “open” with Philipp Krenn</a> — The Changelog</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6a22387a44c7" width="1" height="1" alt=""><hr><p><a href="https://medium.com/coding-experiences/15-week-of-the-year-6a22387a44c7">#15 Week of the Year</a> was originally published in <a href="https://medium.com/coding-experiences">Coding experiences</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[#14 Week of the Year]]></title>
            <link>https://medium.com/coding-experiences/14-week-of-the-year-269d716b7582?source=rss-7aee34c55666------2</link>
            <guid isPermaLink="false">https://medium.com/p/269d716b7582</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[blog]]></category>
            <category><![CDATA[learning-to-code]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Florian Dahlitz]]></dc:creator>
            <pubDate>Sun, 08 Apr 2018 17:42:57 GMT</pubDate>
            <atom:updated>2018-04-08T17:42:57.698Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8WLZFZzuc-60GpUz62OxIA.jpeg" /></figure><p><em>Playing around with IPython. Working on the command line. Going on finishing my portfolio page.</em></p><p>This week was the first week I was back studying in Mannheim. After two months of internship it was quite challenging to find back into routine. That’s actually the major reason, why I wasn’t able to code as much as I usually do and as I wanted to. Nevertheless, I coded around most of the days and provide a summary of the challenges I had to deal with and the insights I’ve got.</p><h4>Playing around with IPython</h4><p>For one year now, I do most of the things via the command line, because it’s in my opinion more powerful and — with a little training — faster as well. However, I stayed away from Vim for quite a long time. I only used it, when I wanted to change only one line of code and didn’t want to start a text editor for it. Back at university my professor for object-oriented programming asked us, what IDEs we used in the past. Because in his opinion nobody is working with Vim and the command line only. I told him, that I often use the command line and also Vim for minor edits. Due to the resulting discussion I decided to give it a try and worked the whole lecture only with the command line and Vim. Back home I didn’t stop doing it. Every Python code snippet I’ve made I used Vim for.</p><p>Currently, I’m reading <em>Python Tricks</em> from <a href="https://twitter.com/@dbader_org">Dan Bader</a> and he is making use of IPython a lot. I already was on the command line, so why not using IPython instead of Vim? Most of the things I was doing were for testing and learning purposes only, so no need to save them to a file. Best conditions for using IPython.</p><p>In my sessions I had a closer look at Python’s <em>datetime</em> and <em>time</em> packages. I created a small command line countdown, I nice gimmick for a boring lecture! Have a look at the far easy application:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*44KMcWfavqx3yS0LroqsSA.png" /></figure><p>You can specify the time of the end of the countdown via the command line argument <strong>-t</strong>.</p><p>In the lecture we also had to deal with Java. And guess what? Compiled and ran it via the command line…</p><h4>Python Tricks</h4><p>Over the past week I dived deeper into Dan Bader’s book <em>Python Tricks, </em>which I can recommend to everybody going further using Python. I learned about the use of <em>assert </em>and Python’s lambda-functions.</p><p>Furthermore, I was guided through the creation and usage of closures and decorators. I created several decorators on my own. The most useful is in my opinion the <em>trace</em> decorator, which logs function calls for you:</p><pre>import functools</pre><pre>def trace(func):<br>    @functools.wraps(func)<br>    def wrapper(*args, **kwargs):<br>        print(&quot;-&quot; * 20)<br>        print(f&quot;TRACE: calling {func.__name__}() &quot;<br>              f&quot;with {args}, {kwargs}&quot;)</pre><pre>        original_result = func(*args, **kwargs)</pre><pre>        print(f&quot;TRACE: {func.__name__}() &quot;<br>              f&quot;returned {original_result!r}&quot;)<br>        print(&quot;-&quot; * 20)</pre><pre>        return original_result</pre><pre>    return wrapper</pre><p>Note, that the<strong> @functools.wraps() </strong>is used to protect the loss of meta data. Possible docstring will be available after wrapping the function. The <em>*args</em> and <em>**kwargs</em> ensure, that using arguments is still possible.</p><h4>Additional Stuff</h4><p>It’s worth to mentioned, that I found <a href="https://pymotw.com">PyMOWT</a> (Python Model Of The Week) maintained by <a href="https://twitter.com/doughellmann">Doug Hellmann</a>. This site uncovers one Python model of the standard library every week providing great examples of how to use it and explanations about the existence of it. It’s a very powerful resource to look up certain packages you heard of.</p><p>That’s it. Not so many things to write about as usual, but better than nothing! Wish you a week of great experiences, stay curious and keep coding!</p><h4>Articles and Podcast episodes</h4><p>As always I provide a list of articles I’ve read and episodes I’ve listened to and that are worth sharing.</p><h4>Articles</h4><p>I read only a few articles about programming this week and none of them are worth sharing. First time this section will be left empty.</p><h4>Episodes</h4><ul><li><a href="https://itunes.apple.com/gb/podcast/71-we-can-migrate-to-python-3-careful-please/id1173690032?i=1000407691553&amp;mt=2">#71 We can migrate to Python 3, careful please</a> — Python Bytes</li><li><a href="https://itunes.apple.com/gb/podcast/72-new-versioning-episode-0-0-7-2-with-72-releases/id1173690032?i=1000408261667&amp;mt=2">#72 New versioning: Episode 0.0.7.2 (with 72 releases)</a> — Python Bytes</li><li><a href="https://itunes.apple.com/gb/podcast/cr244-das-ende-von-facebook/id135057225?i=1000408032168&amp;mt=2">CR244 Das Ende von Facebook?</a> — Chaosradio</li><li><a href="https://itunes.apple.com/gb/podcast/157-the-journal-of-open-source-software/id979020229?i=1000408335803&amp;mt=2">#157 The Journal of Open Source Software</a> — Talk Python To Me</li><li><a href="https://itunes.apple.com/gb/podcast/how-we-can-teach-computers-to-make-sense-our-emotions/id160904630?i=1000408006788&amp;mt=2">How we can teach computers to make sense of our emotions | Raphael Arar</a> — TED Talks Daily</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=269d716b7582" width="1" height="1" alt=""><hr><p><a href="https://medium.com/coding-experiences/14-week-of-the-year-269d716b7582">#14 Week of the Year</a> was originally published in <a href="https://medium.com/coding-experiences">Coding experiences</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>