<?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: Muhammad Syuqri</title>
    <description>The latest articles on Forem by Muhammad Syuqri (@dansyuqri).</description>
    <link>https://forem.com/dansyuqri</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%2F49076%2F233a7c21-5815-4414-8760-b87a559975d2.jpg</url>
      <title>Forem: Muhammad Syuqri</title>
      <link>https://forem.com/dansyuqri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dansyuqri"/>
    <language>en</language>
    <item>
      <title>saferm - A tool to safely remove files on CLI</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Fri, 28 Aug 2020 09:15:49 +0000</pubDate>
      <link>https://forem.com/dansyuqri/saferm-a-tool-to-safely-remove-files-on-cli-2nhl</link>
      <guid>https://forem.com/dansyuqri/saferm-a-tool-to-safely-remove-files-on-cli-2nhl</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;I started this toy project to learn about Golang and have some experience using it. Test-Driven Development and GitHub Actions were side learning points for this project.&lt;/p&gt;

&lt;p&gt;I have been doing development in the past which did not prioritise automated testing. As a result, extensive manual testing at the end of each development iteration was required and it definitely was a pain. I wanted to take a different approach and learn the methodology behind &lt;strong&gt;TDD&lt;/strong&gt; so that each iteration of the development process can go through automated testing and can be published with confidence.&lt;/p&gt;

&lt;p&gt;I decided to go into GitHub Actions by submitting my first GitHub Action - &lt;a href="https://dev.to/dansyuqri/newbiefy-make-your-repo-beginner-friendly-again-12ck"&gt;Newbiefy&lt;/a&gt; (Wacky Wildcards Category) - as part of the &lt;a href="https://dev.to/devteam/announcing-the-github-actions-hackathon-on-dev-3ljn"&gt;DEV x GitHub Actions Hackathon&lt;/a&gt;. This toy project builds on the knowledge from that experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is &lt;code&gt;saferm&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;You know when you want to delete a repository from GitHub, they ask for the name of the repository as confirmation of the deletion so that they know it is by choice, not accident? &lt;code&gt;saferm&lt;/code&gt; does exactly that when you are trying to remove files from a directory using the command-line. Each file it discovers will prompt the user to input the filename before deletion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why &lt;code&gt;saferm&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Apart from the learning reasons as mentioned before, there is one thing that I found in the &lt;code&gt;rm&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;The conventional &lt;code&gt;rm&lt;/code&gt; command does have an interactive mode using the &lt;code&gt;-i&lt;/code&gt; flag. However, this only prompts the user for a &lt;code&gt;Y/y + Enter&lt;/code&gt; response.&lt;/p&gt;

&lt;p&gt;The purpose of &lt;code&gt;saferm&lt;/code&gt; is to make the deletion process more painstaking so that the user will take ownership of the deletion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check it out here
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Dansyuqri"&gt;
        Dansyuqri
      &lt;/a&gt; / &lt;a href="https://github.com/Dansyuqri/saferm"&gt;
        saferm
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This repository is a project for me to explore Go.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
saferm&lt;/h1&gt;
&lt;p&gt;A command-line tool for removing files from a directory in a safe fashion. Written in Go.&lt;/p&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;First, install or update the &lt;code&gt;saferm&lt;/code&gt; binary into you &lt;code&gt;$GOPATH&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;$ go get -u github.com/dansyuqri/saferm&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;p&gt;You can immediately use the &lt;code&gt;saferm&lt;/code&gt; command on your cli.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;$ saferm&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;By default, the &lt;code&gt;saferm&lt;/code&gt; works on the current working directory. In order to specify another directory, you will need to supplement the &lt;code&gt;-p&lt;/code&gt; flag like so:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;$ saferm -p /home/user/Downloads&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The above command immediately starts giving you a filename for you to input in order to delete the file:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell"&gt;&lt;pre&gt;$ saferm -p /home/user/Downloads
Enter filename to confirm deletion
testfile.txt
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once you have entered the exact filename, it will proceed to delete the file. This painstaking process of typing the exact name of the file will assure you that the deletion is by choice, not accident (similar to how deletion of a repository…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Dansyuqri/saferm"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Definitely open to feedback and suggestions, be it on the code or TDD methodology that I was trying to adopt. Leave them below thank you!&lt;/p&gt;

</description>
      <category>go</category>
      <category>showdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why Python Generators?</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Fri, 28 Aug 2020 05:33:24 +0000</pubDate>
      <link>https://forem.com/dansyuqri/why-python-generators-b4o</link>
      <guid>https://forem.com/dansyuqri/why-python-generators-b4o</guid>
      <description>&lt;p&gt;In the usual use case of iterating over an iterable object such as a &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;string&lt;/code&gt;, or &lt;code&gt;dict&lt;/code&gt;, we can simply use a &lt;code&gt;for&lt;/code&gt; loop to go through each element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;my_numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;my_numbers&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;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# prints numbers from 0 to 4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can also achieve a similar result using generators. To instantiate a generator, one can simply change the &lt;code&gt;[]&lt;/code&gt; to &lt;code&gt;()&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;my_numbers_gen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# this is now a generator
&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;my_numbers_gen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# ouput &amp;gt;&amp;gt;&amp;gt; &amp;lt;generator object my_numbers_gen.&amp;lt;locals&amp;gt;.&amp;lt;genexpr&amp;gt; at 0x7f53ebcb1f20&amp;gt;
&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;my_numbers_gen&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;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# prints numbers from 0 to 4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can see that &lt;code&gt;my_numbers_gen&lt;/code&gt; is of the type &lt;code&gt;generator object&lt;/code&gt;. When we iterate through the generator object and the list, we can see that there is no difference in the output. Why would you then want to use a generator?&lt;/p&gt;

&lt;h3&gt;
  
  
  Reasons to use a generator
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Reduce memory usage when iterating over large objects
&lt;/h4&gt;

&lt;p&gt;When we iterate over a large &lt;code&gt;list&lt;/code&gt;, say with 1 million elements, we can use &lt;a href="https://pypi.org/project/memory-profiler/"&gt;memory profiler&lt;/a&gt; to see that the memory usage jumps from 13.992 MiB to 52.895 MiB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;syuqri@pop-os:~/Documents&lt;span class="nv"&gt;$ &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; memory_profiler test.py 
Filename: test.py

Line &lt;span class="c"&gt;#    Mem usage    Increment   Line Contents&lt;/span&gt;
&lt;span class="o"&gt;================================================&lt;/span&gt;
     2   13.992 MiB   13.992 MiB   @profile
     3                             def test_func&lt;span class="o"&gt;()&lt;/span&gt;:
     4   52.895 MiB    0.309 MiB       test_list &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;x &lt;span class="k"&gt;for &lt;/span&gt;x &lt;span class="k"&gt;in &lt;/span&gt;range&lt;span class="o"&gt;(&lt;/span&gt;10&lt;span class="k"&gt;**&lt;/span&gt;6&lt;span class="o"&gt;)]&lt;/span&gt;
     5   52.895 MiB    0.000 MiB       &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in &lt;/span&gt;test_list:
     6   52.895 MiB    0.000 MiB           pass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;On the other hand, the generator version of this sees no increment in the memory usage. This is because an iterator does not load all of its values into memory at once. Instead, it loads one value and then proceeds to the next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;syuqri@pop-os:~/Documents&lt;span class="nv"&gt;$ &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; memory_profiler test_gen.py 
Filename: test_gen.py

Line &lt;span class="c"&gt;#    Mem usage    Increment   Line Contents&lt;/span&gt;
&lt;span class="o"&gt;================================================&lt;/span&gt;
     1   14.000 MiB   14.000 MiB   @profile
     2                             def test_func_gen&lt;span class="o"&gt;()&lt;/span&gt;:
     3   14.000 MiB    0.000 MiB       test_gen &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;x &lt;span class="k"&gt;for &lt;/span&gt;x &lt;span class="k"&gt;in &lt;/span&gt;range&lt;span class="o"&gt;(&lt;/span&gt;10&lt;span class="k"&gt;**&lt;/span&gt;6&lt;span class="o"&gt;))&lt;/span&gt;
     4   14.000 MiB    0.000 MiB       &lt;span class="k"&gt;for &lt;/span&gt;i &lt;span class="k"&gt;in &lt;/span&gt;test_gen:
     5   14.000 MiB    0.000 MiB           pass
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  You need to use intermediate values from a function
&lt;/h4&gt;

&lt;p&gt;In a typical function, you can have multiple &lt;code&gt;return&lt;/code&gt; statements, but ultimately, only one of those &lt;code&gt;return&lt;/code&gt; statements holds true.&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;normal_func&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"goodbye"&lt;/span&gt;

&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normal_func&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;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we run the above snippet, we can see the output is always &lt;code&gt;"hello"&lt;/code&gt;. What if we want both strings to be printed out?&lt;/p&gt;

&lt;p&gt;Well, that is where generators can come in handy. The major difference change needed to the above function to make it a generator is to use &lt;code&gt;yield&lt;/code&gt; instead of &lt;code&gt;return&lt;/code&gt;.&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;gen_func&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s"&gt;"goodbye"&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gen_func&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="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&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="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;goodbye&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Since the function is a generator, we can iterate through the different &lt;code&gt;yield&lt;/code&gt; statements of the function using &lt;code&gt;next()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.programiz.com/python-programming/generator"&gt;https://www.programiz.com/python-programming/generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>codenewbie</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Newbiefy - Make Your Repo Beginner Friendly Again</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Fri, 21 Aug 2020 05:51:46 +0000</pubDate>
      <link>https://forem.com/dansyuqri/newbiefy-make-your-repo-beginner-friendly-again-12ck</link>
      <guid>https://forem.com/dansyuqri/newbiefy-make-your-repo-beginner-friendly-again-12ck</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;Makes your repository beginner friendly by removing everything in place of a hello_world file in the mostly used language of the repo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Wacky Wildcards&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&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/Dansyuqri" rel="noopener noreferrer"&gt;
        Dansyuqri
      &lt;/a&gt; / &lt;a href="https://github.com/Dansyuqri/newbiefy" rel="noopener noreferrer"&gt;
        newbiefy
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Makes your repository beginner friendly by removing everything in place of a hello_world.&amp;lt;ext&amp;gt; in the mostly used language of the repo.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a href="https://dev.to" alt="dev.to" rel="nofollow"&gt;
    &lt;img src="https://camo.githubusercontent.com/18f625ad610b08a1f515f2bc26ed110cb00b23d78d4f7d7a58fc3c056c96630f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6465762e746f2d6861636b6174686f6e2d626c7565"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/Dansyuqri/newbiefy/actions?query=workflow%3Abuild-test" alt="workflow build-test" rel="noopener noreferrer"&gt;
    &lt;img src="https://github.com/Dansyuqri/newbiefy/workflows/build-test/badge.svg"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/Dansyuqri/newbiefy/blob/main/LICENSE" alt="license" rel="noopener noreferrer"&gt;
    &lt;img src="https://camo.githubusercontent.com/bb4e5c0036a6a8cdbc59b38d44f09ad8f6dc722751dad34d3df5bf0ac61913c1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c7565"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Newbiefy&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;The Action you never knew you needed.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Makes your repository beginner friendly by removing all source code and putting a hello world file (in the most used language of the repo) in its place.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Why not&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="highlight highlight-source-yaml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;dansyuqri/newbiefy@latest&lt;/span&gt;
  &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;github-token&lt;/span&gt;: &lt;span class="pl-s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Additional Info&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Currently it supports the following languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;C&lt;/li&gt;
&lt;li&gt;C++&lt;/li&gt;
&lt;li&gt;C#&lt;/li&gt;
&lt;li&gt;Visual Basic .NET&lt;/li&gt;
&lt;li&gt;JavaScript&lt;/li&gt;
&lt;li&gt;PHP&lt;/li&gt;
&lt;li&gt;Objective-C&lt;/li&gt;
&lt;li&gt;SQL&lt;/li&gt;
&lt;li&gt;Ruby&lt;/li&gt;
&lt;li&gt;MATLAB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The codes have been referred from &lt;a href="https://towardsdatascience.com/how-to-print-hello-world-in-top-12-most-popular-programming-languages-736d49c6c61c" rel="nofollow noopener noreferrer"&gt;this page&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;Head over to &lt;a href="https://github.com/Dansyuqri/newbiefy-test" rel="noopener noreferrer"&gt;the test page&lt;/a&gt; for a demo.&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Dansyuqri/newbiefy" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Dansyuqri/newbiefy-test" rel="noopener noreferrer"&gt;https://github.com/Dansyuqri/newbiefy-test&lt;/a&gt;&lt;br&gt;
source codes for the different languages were from &lt;a href="https://towardsdatascience.com/how-to-print-hello-world-in-top-12-most-popular-programming-languages-736d49c6c61c" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>actionshackathon</category>
      <category>github</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Pub/sub with PyZMQ: Part 2</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Sun, 12 Apr 2020 10:33:18 +0000</pubDate>
      <link>https://forem.com/dansyuqri/pub-sub-with-pyzmq-part-2-2f63</link>
      <guid>https://forem.com/dansyuqri/pub-sub-with-pyzmq-part-2-2f63</guid>
      <description>&lt;p&gt;Hello everyone! I hope everyone is keeping healthy and staying safe. I hope that you have had a good meal before this, as I will be enticing you with a couple of breakfast analogies for this PyZMQ tutorial :P&lt;/p&gt;

&lt;p&gt;This post is a continuation in the "Pub/sub with PyZMQ" series. Part 1 can be found &lt;a href="https://dev.to/dansyuqri/pub-sub-with-pyzmq-part-1-2f63"&gt;here&lt;/a&gt;. This part will build upon what we have discussed in the previous one. Do feel free to revisit Part 1 as a recap or if you are new to this series.&lt;/p&gt;

&lt;p&gt;The overview for this post will be as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple Subscribers to One Publisher&lt;/li&gt;
&lt;li&gt;Single Subscriber to Multiple Publishers&lt;/li&gt;
&lt;li&gt;Using Poller to Prevent Code Blocking&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Multiple Subscribers to One Publisher
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79063186-baf7cd80-7cd2-11ea-86f6-dd3f92b99898.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79063186-baf7cd80-7cd2-11ea-86f6-dd3f92b99898.png" alt="multiple subscribers to one publisher diagram"&gt;&lt;/a&gt;&lt;/p&gt;
Multiple subscribers to one publisher diagram



&lt;p&gt;This pattern is extremely useful for when the same data is required by multiple subscribers from a common publisher. An example use case would be a home automation system that consists of appliances connected to smart plugs. Let's say you wake up in the morning and would like your breakfast to be prepared automatically while you have your shower. You would like for your toaster and coffee maker to be started as soon as you turn on the lights in your bathroom.&lt;/p&gt;

&lt;p&gt;Instead of using the server/client pattern in which both the toaster and coffee maker constantly requests for the status of the light switch in your bathroom, the light switch instead tells both the toaster and coffee maker when it is time to turn on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79063569-175bec80-7cd5-11ea-9146-d86c1f97e4e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79063569-175bec80-7cd5-11ea-9146-d86c1f97e4e0.png" alt="toaster and coffee maker analogy diagram"&gt;&lt;/a&gt;&lt;/p&gt;
Toaster and coffee maker analogy



&lt;p&gt;Using the &lt;code&gt;Thread&lt;/code&gt; class from the &lt;code&gt;threading&lt;/code&gt; module in Python, we can simulate this scenario. First, we create the two subscribers like so:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We create two threads which simulate the coffee maker and toaster listeners. The listeners are subscribed to the 'light' topic and await for any messages coming from the 'light' publisher.&lt;/p&gt;

&lt;p&gt;We can then fire this script up and continue to the next step - creating the single 'light' switch publisher. As you will notice again, the threads will be blocked due to the &lt;code&gt;recv_string()&lt;/code&gt; function in both the coffee make and toaster threads.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Once the &lt;code&gt;single_pub.py&lt;/code&gt; script has also been run, it will have a sleep for 1 second (reason for sleep &lt;a href="https://dev.to/dansyuqri/pub-sub-with-pyzmq-part-1-2f63#getting-started"&gt;here&lt;/a&gt;) before the publisher sends the message to the coffee maker and toaster threads. The results can then be seen:&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; python multi_sub.py
COFFEE MAKER received &lt;span class="s1"&gt;'light is ON'&lt;/span&gt; from light.
TOASTER received &lt;span class="s1"&gt;'light is ON'&lt;/span&gt; from light.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: It is better to create a new &lt;code&gt;socket&lt;/code&gt; instance in each thread as demonstrated. This is because the &lt;code&gt;socket&lt;/code&gt; objects are not thread-safe. The context however, can be shared. More info &lt;a href="https://pyzmq.readthedocs.io/en/latest/morethanbindings.html#thread-safety" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Single Subscriber to Multiple Publishers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79064381-057d4800-7cdb-11ea-9687-0ae0d7c8f44f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79064381-057d4800-7cdb-11ea-9687-0ae0d7c8f44f.png" alt="Single subscriber to multiple publishers diagram"&gt;&lt;/a&gt;&lt;/p&gt;
Single subscriber to multiple publishers diagram



&lt;p&gt;We can bring in a new element into our coffee maker and toaster analogy. This time, let's include a smart mirror in your bathroom. After you are done showering, you get ready for your day ahead and prepare yourself using the smart mirror. The mirror tells you if your coffee and toast are ready or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79064669-6148d080-7cdd-11ea-8869-c4b62c454fa0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F10414279%2F79064669-6148d080-7cdd-11ea-8869-c4b62c454fa0.png" alt="smart mirror analogy"&gt;&lt;/a&gt;&lt;/p&gt;
Smart mirror analogy



&lt;p&gt;For this set of code, we shall utilise the multipart messaging of PyZMQ. This way, we can separate the topic and the actual message that we want. Recap on the multipart messaging can be found &lt;a href="https://dev.to/dansyuqri/pub-sub-with-pyzmq-part-1-2f63#multipart-messages"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's start off with the single subscriber code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;The main difference between &lt;code&gt;single_sub.py&lt;/code&gt; and &lt;code&gt;single_pub.py&lt;/code&gt; is the multipart message implementation and that &lt;code&gt;single_sub.py&lt;/code&gt; is receiving messages instead of sending.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;multi_pub.py&lt;/code&gt; code now utilises the &lt;code&gt;Thread&lt;/code&gt; class and instantiates two threads to send messages concurrently.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We now have the topic and status of each appliance sent in separate parts of the messages. Again, the flag &lt;code&gt;zmq.SNDMORE&lt;/code&gt; is the one that establishes that there are more parts to the message, and the receiver needs to prepare to receive the remaining messages. The topic is always the first part of the message, which makes it easier for us to distinguish topic from message. This results in the following:&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="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;single_sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; 
&lt;span class="n"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;COFFEE&lt;/span&gt; &lt;span class="n"&gt;MAKER&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TOASTER&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Poller to Prevent Code Blocking
&lt;/h2&gt;

&lt;p&gt;As you might have noticed in previous examples, all variants of the &lt;code&gt;recv()&lt;/code&gt; function blocks the code execution. As such, it can be annoying to have to force close your terminal each time you run your code and the &lt;code&gt;recv()&lt;/code&gt; statement is within an infinite loop. &lt;/p&gt;

&lt;p&gt;We can overcome this by using the &lt;code&gt;zmq.Poller()&lt;/code&gt; object. It mirrors the built-in Python poll interface. Essentially, it checks whether the file descriptor created during the socket creation in the &lt;code&gt;context.socket()&lt;/code&gt; function call, has any pending I/O events. &lt;/p&gt;

&lt;p&gt;We can instantiate a Poller object like so:&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;poller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Poller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We then have to register a socket to the poller object so that it knows which file descriptors to check for I/O events.&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;poller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POLLIN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;zmq.POLLIN&lt;/code&gt; indicates that the check whether any data is ready to be read or not at the socket's file descriptor. &lt;/p&gt;

&lt;p&gt;We can then use our previous &lt;code&gt;single_sub.py&lt;/code&gt; and build upon it. Let's call the new script &lt;code&gt;simple_poller.py&lt;/code&gt;. We can introduce a check for events with a timeout in the &lt;code&gt;while&lt;/code&gt; loop.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Each iteration of the loop, once the timeout limit has been reached for the poll event, the &lt;code&gt;if&lt;/code&gt; code block is executed, before continuing into the next iteration of the loop. This way, break/interrupt events can cause the script to exit within this small time frame.&lt;/p&gt;




&lt;h2&gt;
  
  
  Future Guides
&lt;/h2&gt;

&lt;p&gt;I hope that this second segment of the series has served as a good build on Part 1. As a recap, this post has covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Multiple subscriber to single publisher&lt;/li&gt;
&lt;li&gt;  Single subscriber to multiple publisher&lt;/li&gt;
&lt;li&gt;  Using poller to prevent code blocking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these small parts, I hope that you will be able to apply some of these concepts into your own personal projects. For the next post, I do hope to cover the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  N-to-N publisher/subscriber messaging&lt;/li&gt;
&lt;li&gt;  Implementing a Web Socket forwarder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the links for the codes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://gist.github.com/Dansyuqri/3b533d0f11f3ddd53da34686434309d7" rel="noopener noreferrer"&gt;Multi Sub to Single Pub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://gist.github.com/Dansyuqri/93b8df592946cf5ec2158aa10c13bbcc" rel="noopener noreferrer"&gt;Single Sub to Multi Pub (includes poller)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading! I do hope to learn from your feedback and comments. Also, do share if you have implemented any of these patterns to your projects! I would love to see them in action :D&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>pubsub</category>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Pub/sub with PyZMQ: Part 1</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Sun, 08 Mar 2020 08:54:59 +0000</pubDate>
      <link>https://forem.com/dansyuqri/pub-sub-with-pyzmq-part-1-2f63</link>
      <guid>https://forem.com/dansyuqri/pub-sub-with-pyzmq-part-1-2f63</guid>
      <description>&lt;p&gt;This series of guides will go into the usage of the publish-subscribe pattern with PyZMQ. I will start off with simple examples and then go into some of the use cases that I have applied using this pattern. You will find Gists with sample code to get you started with.&lt;/p&gt;

&lt;p&gt;Here are the topics I will go through for this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is publish/subscribe?&lt;/li&gt;
&lt;li&gt;What is PyZMQ?&lt;/li&gt;
&lt;li&gt;Getting started&lt;/li&gt;
&lt;li&gt;Specifying topics&lt;/li&gt;
&lt;li&gt;Multipart messages&lt;/li&gt;
&lt;li&gt;Future Guides&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is publish/subscribe?
&lt;/h2&gt;

&lt;p&gt;It is a messaging pattern that is meant for allowing senders to send their messages to recipients without having to know who their recipients are. The senders are known as publishers while the recipients are known as subscribers.&lt;/p&gt;

&lt;p&gt;A simple analogy for this pattern would be a convention. A convention can be held in a large hall. In the hall there may be multiple sections for speakers to give their talks at. A speaker can give his/her talk regardless of whether or not anyone is listening. As attendees, we can roam around and drop in at any of these sections to listen to any speaker. When we sit in at a particular section, we are only listening to a single speaker. The speakers in this analogy refer to the publishers, while attendees refer to the subscribers.&lt;/p&gt;

&lt;p&gt;In this guide, I will be covering a one-to-one publish/subscribe pattern, which simplifies the explanation process for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is PyZMQ?
&lt;/h2&gt;

&lt;p&gt;PyZMQ is the Python-based binding for the popular open-source &lt;a href="https://zeromq.org/"&gt;ZeroMQ&lt;/a&gt; (ØMQ/ZMQ) messaging library. ZMQ comes with no messaging brokers on the side, meaning that there is no intermediary server/module which is needed to translate the messages sent between sender and recipient to a uniform messaging protocol. This makes ZMQ lightweight and easy to get started with.&lt;/p&gt;

&lt;p&gt;ZMQ also comes with support for multiple messaging patterns apart from pubsub and programming languages, allowing cross-language communication. However, this guide will only be focusing on the pubsub pattern in Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Install the pyzmq package&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install pyzmq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can then proceed to write a simple publisher to start sending out messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# simple_pub.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zmq&lt;/span&gt;

&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"5001"&lt;/span&gt;

&lt;span class="c1"&gt;# Creates a socket instance
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PUB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Binds the socket to a predefined port on localhost
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp://{}:{}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Sends a string message
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The publisher script will run and send a single message with the string &lt;code&gt;"hello"&lt;/code&gt; and exit.&lt;/p&gt;

&lt;p&gt;The subscriber code can be written as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# simple_sub.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zmq&lt;/span&gt;

&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"5001"&lt;/span&gt;

&lt;span class="c1"&gt;# Creates a socket instance
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SUB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Connects to a bound socket
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp://{}:{}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Subscribes to all topics
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Receives a string format message
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The subscriber code is very similar to the publisher one. The only difference is that the subscriber will now connect to the publisher socket to receive messages from the publisher. The subscriber can also subscribe to certain topics, but for the example above, we will subscribe to all topics indicated by the empty string.&lt;/p&gt;

&lt;p&gt;Open up a terminal. If you try to run the &lt;code&gt;simple_sub&lt;/code&gt; code now, you will see that the code execution is blocked. This is because &lt;code&gt;socket.recv_string()&lt;/code&gt; is blocking the execution, waiting for a message to be received. You cannot interrupt the execution using the &lt;code&gt;ctrl+Z&lt;/code&gt; command as well. As such, it can be quite troublesome to always have to close the terminal window to force the code to exit or run the publisher code to ensure the completion of the subscriber code. Let's use either of these simple solutions for now.&lt;/p&gt;

&lt;p&gt;Open up a separate terminal. When you run &lt;code&gt;simple_pub&lt;/code&gt;, you might expect that the subscriber would receive the message. However, this will not be the case as &lt;code&gt;bind()&lt;/code&gt; executes in an asynchronous manner. This means that the entire script actually finishes even before the &lt;code&gt;bind()&lt;/code&gt; statement manages to complete.&lt;/p&gt;

&lt;p&gt;Let's edit &lt;code&gt;simple_pub&lt;/code&gt; to include a &lt;code&gt;sleep&lt;/code&gt; statement, which is a simplified solution to this problem. This way, the asynchronous &lt;code&gt;bind()&lt;/code&gt; should run to completion before the publishing of the message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# simple_pub.py
&lt;/span&gt;
&lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="c1"&gt;# Binds the socket to a predefined port on localhost
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp://{}:{}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# new sleep statement
&lt;/span&gt;
&lt;span class="c1"&gt;# Receives a string format message
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's run the publisher code again. &lt;/p&gt;

&lt;p&gt;Now we can see that the code execution in &lt;code&gt;simple_sub&lt;/code&gt; has run to completion and printed out the word &lt;code&gt;hello&lt;/code&gt; in string format. If we use the generic &lt;code&gt;socket.recv()&lt;/code&gt;, we will end up with a &lt;code&gt;bytes&lt;/code&gt; type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;hello&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="s"&gt;b'hello'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;It really depends on the use case as PyZMQ provides a few functions to send and receive different serialized/encoded messages. These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;send_json&lt;/code&gt;/&lt;code&gt;recv_json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send_multipart&lt;/code&gt;/&lt;code&gt;recv_multipart&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send_pyobj&lt;/code&gt;/&lt;code&gt;recv_pyobj&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send_serialized&lt;/code&gt;/&lt;code&gt;recv_serialized&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details on each of these can be found in the &lt;a href="https://pyzmq.readthedocs.io/en/latest/api/zmq.html#zmq.Socket"&gt;PyZMQ Socket docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Specifying topics
&lt;/h2&gt;

&lt;p&gt;In the pubsub pattern, subscribing to a topic means that you only listen in for particular messages that you are interested in and disregard the rest.&lt;/p&gt;

&lt;p&gt;Using the convention analogy again, let's say you would like to only listen to certain segments of speaker A's presentation. You are only interested in Machine Learning and Blockchain topics, but find other topics a bore. Whenever the speaker mentions Machine Learning, you take down the notes related to that topic. Whenever the speaker mentions Blockchain, you take down the notes related to that topic. Whenever the speaker mentions Dev.to, you close your notebook and ignore whatever he/she says. This is what subscribing to a topic in the pubsub pattern equates to.&lt;/p&gt;

&lt;p&gt;To do this with PyZMQ, you can use &lt;code&gt;socket.subscribe()&lt;/code&gt;. Previously, we have subscribed to all topics by using &lt;code&gt;.subscribe("")&lt;/code&gt;. From the high-level perspective, the function allows us to subscribe to a topic. What we do not see are the inner workings of ZMQ, which actually creates a filter to sieve the messages that we are interested in. I will not elaborate too much on this as it can be found &lt;a href="http://api.zeromq.org/master:zmq-setsockopt"&gt;here&lt;/a&gt; for your leisurely read.&lt;/p&gt;

&lt;p&gt;Let us now only subscribe to the topic &lt;code&gt;"ML"&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# simple_sub.py
&lt;/span&gt;
&lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="c1"&gt;# Subscribes to all topics
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ML"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Receives a string format message
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This means that any message published starting with &lt;code&gt;"ML"&lt;/code&gt; will be received by the subscriber. So, we have to alter the messages sent by the publisher to achieve this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# simple_pub.py
&lt;/span&gt;
&lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="c1"&gt;# Sends a string message
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ML hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;When we run the code, we can see that the message is received by the subscriber. To demonstrate that all other topics are filtered out, you can try changing the &lt;code&gt;"Dev.to"&lt;/code&gt; in the subscriber code to any other characters and you will see that the code execution for the subscriber will be blocked again, indicating that it has not received messages based on the topics it has subscribed to.&lt;/p&gt;

&lt;p&gt;So now, we have the topic and the actual message that we want combined together into a single message that is sent from the publisher. We can use &lt;code&gt;.split()&lt;/code&gt; to separate the topic and actual message in the subscriber.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# simple_sub.py
&lt;/span&gt;
&lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="n"&gt;whole_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actual_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;whole_message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Alternatively, we can use &lt;code&gt;send_multipart()&lt;/code&gt; and &lt;code&gt;recv_multipart()&lt;/code&gt; accordingly, which will be explained next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multipart messages
&lt;/h2&gt;

&lt;p&gt;Multipart messages are sent from the publisher by including all of your message parts together with a flag which indicates more message parts are to follow. When we were using &lt;code&gt;send_string()&lt;/code&gt;, we were only sending a single message disguised as two parts separated by a space. &lt;/p&gt;

&lt;p&gt;Now, we shall attempt to use &lt;code&gt;send_multipart()&lt;/code&gt; in the publisher to send two separate parts so that the topic and message can be distinguished without using any &lt;code&gt;split()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# multipart_pub.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zmq&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;

&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"5001"&lt;/span&gt;

&lt;span class="c1"&gt;# Creates a socket instance
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PUB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Binds the socket to a predefined port on localhost
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp://{}:{}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sends a multipart message
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_multipart&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s"&gt;b"ML"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b"hello"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When using &lt;code&gt;.send()&lt;/code&gt; and &lt;code&gt;.send_multipart()&lt;/code&gt;, the message/message parts need to be &lt;code&gt;bytes&lt;/code&gt; type respectively. Previously when we were using &lt;code&gt;send_string()&lt;/code&gt;, the function helped us encode the string into bytes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# multipart_sub.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zmq&lt;/span&gt;

&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"5001"&lt;/span&gt;

&lt;span class="c1"&gt;# Creates a socket instance
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SUB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Connects to a bound socket
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tcp://{}:{}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Subscribes to all topics
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ML"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Receives a multipart message
&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;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_multipart&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After running both scripts together, we can see the output of the execution in &lt;code&gt;multipart_sub&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;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;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_multipart&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;b'ML'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b'hello'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first element in the list is the topic while the second one is the message part which we are interested in. &lt;/p&gt;

&lt;p&gt;You can also craft your own multipart message by using the &lt;code&gt;zmq.SNDMORE&lt;/code&gt; flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# multipart_pub.py
&lt;/span&gt;
&lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="c1"&gt;# Sends the first part
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ML"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SNDMORE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Sends the second part
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are no flags applied to the second message because the default flag is &lt;code&gt;0&lt;/code&gt;, which indicates that there are now more parts following the message part being sent. The subscriber will still receive the same multipart message as shown previously.&lt;/p&gt;

&lt;p&gt;In a more realistic scenario, you might want to send a JSON instead so that key/value retrieval can be done. To do this, simply replace &lt;code&gt;send_string()&lt;/code&gt; in the second part with &lt;code&gt;send_json()&lt;/code&gt;. &lt;code&gt;send_json()&lt;/code&gt;  will automatically serialize the dictionary that you pass to it into JSON format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# multipart_pub.py
&lt;/span&gt;
&lt;span class="c1"&gt;# ...
&lt;/span&gt;
&lt;span class="c1"&gt;# Sends the first part
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ML"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;zmq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SNDMORE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Sends the second part
&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The end result on the subscriber end would be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;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;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_multipart&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;b'ML'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;b'{"message":"hello"}'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To ease the deserialization of the JSON back into a Python dictionary, we can use the &lt;code&gt;recv_json()&lt;/code&gt; function instead. We can replace the &lt;code&gt;recv_multipart()&lt;/code&gt; with two lines of code as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# print(socket.recv_multipart()) 
&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;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_string&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;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv_json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which will then yield the following results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ML&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'hello'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Future Guides
&lt;/h2&gt;

&lt;p&gt;I hope that this post serves as a good starting point for anyone who might be keen on using the pubsub pattern with PyZMQ. For this post, I have mainly focused on the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single publisher to single subscriber messaging&lt;/li&gt;
&lt;li&gt;Subscribing to topics&lt;/li&gt;
&lt;li&gt;Sending/receiving multipart messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the next post, I do hope to cover the following to come up with solutions with some of the limitations touched on in this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1-to-N/N-to-1 publisher/subscriber messaging&lt;/li&gt;
&lt;li&gt;N-to-N publisher/subscriber messaging&lt;/li&gt;
&lt;li&gt;Using Poller to prevent code execution blocking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are the links for the codes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/Dansyuqri/c7e8f4bf1d93cf376da8374d0324767b"&gt;simple pubsub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/Dansyuqri/9eea1c4affa27b9d5ad138fd508e8026"&gt;multipart pubsub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading! I do hope to learn from your feedback and comments, so feel free do drop them below.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>pubsub</category>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How to sprinkle some exercise into your developer lifestyle</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Fri, 01 Mar 2019 14:51:19 +0000</pubDate>
      <link>https://forem.com/dansyuqri/how-to-sprinkle-some-exercise-into-your-developer-lifestyle-4o06</link>
      <guid>https://forem.com/dansyuqri/how-to-sprinkle-some-exercise-into-your-developer-lifestyle-4o06</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2Fw7MrzeSg-k0%2Fhqdefault.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2Fw7MrzeSg-k0%2Fhqdefault.jpg" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are all too familiar with the excuses we give ourselves. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Maybe I will do some exercise after work later on"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And when you reach home...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Maybe tomorrow morning before work"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And when the next morning comes&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Oh my, I am going to be late for work"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the cycle continues. After work, we would probably want to wind down, or take on some personal challenges and explore new technologies. We tend to have little to no time for taking care of our bodies. However, we need to remember that when we take our bodies for granted, it may affect our minds - the very tool we use every day.&lt;/p&gt;

&lt;p&gt;This isn't a post on why you should do it. I am in no way a fitness expert. But I would like to share what has worked for me and how you might also be able to achieve little bits of exercise throughout the day, considering the hectic lifestyle you might have.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add mini exercises to your daily routine
&lt;/h2&gt;

&lt;p&gt;Let me share with you a couple of tricks I have been able to come up with just to make myself walk more. You might think that walking doesn't do much, but if you do it on a collective and daily basis, it works wonders. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/DeidU9jiZ62ys/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/DeidU9jiZ62ys/giphy.gif" alt="walk"&gt;&lt;/a&gt;&lt;/p&gt;
Come hooman let's walk



&lt;h3&gt;
  
  
  Take the stairs
&lt;/h3&gt;

&lt;p&gt;You take the public/personal transport and arrive at your office building. Say your cubicle is on the 2nd/3rd/4th floor of the building. Why not take the stairs? Imagine heading up to the 4th floor by stairs everyday. Assuming you have to take the stairs 2 times daily (one just before work, and one after lunch), you would have scaled the total height equivalent to that of Mount Everest in just a year! Who needs to climb the real mountain when you can climb it everyday in your own city :P&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/SaqRhlVBSqFUs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/SaqRhlVBSqFUs/giphy.gif" alt="conquer"&gt;&lt;/a&gt;&lt;/p&gt;
ohhhh yeaaahhhh



&lt;p&gt;If the stairs at work are too cumbersome to access, you would probably have access to some stairs on the way to work. At the train station, up that grand staircase at the park near your home. After work, take the stairs back up to your apartment. Whenever you get the chance, just go for it! &lt;/p&gt;

&lt;p&gt;At first it might seem a bit overwhelming and extremely tiring. The first few times are probably the hardest, both physically and mentally. After a while, it will naturally become a habit and you will want to climb every staircase that you find! (might be exaggerating here a little) You just need to get over that initial bump, and the rest will follow suit :D&lt;/p&gt;

&lt;h3&gt;
  
  
  Go to that toilet which is further away
&lt;/h3&gt;

&lt;p&gt;We all have to go for toilet breaks every now and then (pardon me if you do not). Instead of heading down to the nearest toilet, you could instead head on to the one further away. If there is only one on your floor, head up to the one on the upper or lower floor. This ties closely to the previous point about taking the stairs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/uWXDBmVYdByWreOuRs/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/uWXDBmVYdByWreOuRs/giphy.gif" alt="shhhh"&gt;&lt;/a&gt;&lt;/p&gt;
let me help you with that



&lt;p&gt;Adding more steps to and fro not only helps burn extra calories, but allows for you to give your body a good stretch - something it needs after a long day seated at your desk. Personally, during these walks, I tend to have little sparks ideas as well. Be it finding a new angle to tackle the issue I am currently facing or thinking of new features to add to my work. &lt;/p&gt;

&lt;p&gt;Firstly, because the walk takes away my current form of thinking which is embedded on my screen. Secondly, because it allows a good stretch on my strained back and neck and relaxes my mind a little when I return to my desk. A freshened mind always helps. Perhaps these walks will help you too!&lt;/p&gt;

&lt;p&gt;(Pro tip: Keep yourself hydrated as much as you can. The more water you drink, the more walking you will do)&lt;/p&gt;

&lt;h3&gt;
  
  
  For those who have 10 minutes to spare
&lt;/h3&gt;

&lt;p&gt;10 minutes does not sound like much but if you can focus this time to get your heart pumping, you will break out in a sweat in no time. I usually put 5-10 minutes of my busy days to working out. This usually comes in the form static exercises so that 10 minutes of my time is purely focused on sweating, nothing less. Mobile apps such as &lt;a href="https://play.google.com/store/apps/details?id=homeworkout.homeworkouts.noequipment&amp;amp;hl=en_SG" rel="noopener noreferrer"&gt;Home Workout&lt;/a&gt; (not affiliated to them whatsoever) provide short exercise routines which usually take less than 10 minutes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/QKAB0NihndIw8GtXKE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QKAB0NihndIw8GtXKE/giphy.gif" alt="jump"&gt;&lt;/a&gt;&lt;/p&gt;
We all can jump can't we?



&lt;p&gt;You can even do these during your lunch breaks or any other breaks you might have. The shortest routine on the app consists of just a 3 minute routine (minus the break intervals between each exercise). However, if you manage to get more time, why not attempt a chain of exercise routines after work? Sweat it all out and have a good night's sleep after.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Climb

&lt;ul&gt;
&lt;li&gt;Conquer Mount Everest in your own backyard by climbing all the stairs you can find&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Walk

&lt;ul&gt;
&lt;li&gt;Find the further toilet, cover more distance by walking to it&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Sweat

&lt;ul&gt;
&lt;li&gt;Do static exercises in 10 minutes or less -&amp;gt; &lt;a href="https://play.google.com/store/apps/details?id=homeworkout.homeworkouts.noequipment&amp;amp;hl=en_SG" rel="noopener noreferrer"&gt;Home Workout&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>fitness</category>
      <category>lifestyle</category>
      <category>developer</category>
    </item>
    <item>
      <title>Live in the now</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Sat, 20 Oct 2018 04:40:07 +0000</pubDate>
      <link>https://forem.com/dansyuqri/live-in-the-now-4bl4</link>
      <guid>https://forem.com/dansyuqri/live-in-the-now-4bl4</guid>
      <description>&lt;p&gt;I used to feel extremely exhausted everyday after work, which leaves me with barely any form of motivation to do anything. As a junior developer in the industry, I felt that I need to change the way I do things, so at least when I get home, I still have some energy left to practice my programming because I really do enjoy it. &lt;/p&gt;

&lt;p&gt;I treat programming as my hobby and it makes me happy to be able to solve small challenges through code. However, it was obvious that the mental fatigue was not allowing me to spend time on my hobby. So I decided to change things a little.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I was mentally exhausted?
&lt;/h2&gt;

&lt;p&gt;I was constantly indulging myself in worry at work and at home. It came to me subconsciously and I did not do anything about it other than thinking more about the worries.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if I cannot finish this task?&lt;br&gt;
What if there is an email request from work tonight?&lt;br&gt;
What if? What if...?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There were lots of "what ifs" taking up my brain capacity to the point that it was in a constant loop of worry. After work, the work worries subsided a little, but not too much. It was on repeat over and over again.&lt;/p&gt;

&lt;p&gt;I knew I needed some kind of help or advice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Living in the NOW
&lt;/h2&gt;

&lt;p&gt;I listened to some advices from the audiobook &lt;a href="https://www.audible.com/pd/How-to-Stop-Worrying-and-Start-Living-Audiobook/B002V1OJ3A?source_code=ROWGB13108101800N8&amp;amp;gclid=CjwKCAjwgabeBRBuEiwACD4R5tqR3KtKPuJT3yf_EKX1WaKArDq3NPZTCyX0WiP0Sn443XLGGDhpnRoCQEIQAvD_BwE&amp;amp;gclsrc=aw.ds"&gt;&lt;br&gt;
How to Stop Worrying and Start Living&lt;/a&gt; by Dale Carnegie which says that in order to stop worrying, you just have to be in the now. Not promoting this book, but I feel it may be of some value to others out there who might be in the same situation I was.&lt;/p&gt;

&lt;p&gt;Worries do not help in any day activities at all, apart from wasting my time. So, each time a worry came to mind, I tell myself "Hey there Mr. Syuqri, do not worry about it &lt;strong&gt;NOW&lt;/strong&gt;. Put it in your to-do list and think about it &lt;strong&gt;LATER&lt;/strong&gt;". My worries slowly vanished and they appeared in the form of To-Dos. I schedule each To-Do for a designated time if need be, or leave them floating if they aren't important.&lt;/p&gt;

&lt;p&gt;Although my schedule each day is filled now from day (work) to night (side projects), I feel a sense of ease at each point in time as I am only focused at the task at hand, and nothing else. This certainly helps in productivity and ultimately frees more time for myself - something that worry has never done for me.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;Think and live in the now. Worries should be transformed into To-Dos (scheduled or free floating) and be taken care of later.&lt;/p&gt;

&lt;p&gt;What are you struggles in your busy schedule? How do you overcome them? &lt;/p&gt;

</description>
      <category>productivity</category>
      <category>discuss</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How I used Google Cloud Platform to start investing in stocks</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Sat, 06 Oct 2018 13:38:48 +0000</pubDate>
      <link>https://forem.com/dansyuqri/how-i-used-google-cloud-platform-to-start-investing-in-stocks-34mb</link>
      <guid>https://forem.com/dansyuqri/how-i-used-google-cloud-platform-to-start-investing-in-stocks-34mb</guid>
      <description>&lt;p&gt;I got interested in investing after attending a short talk recommended by a friend of mine. I decided to do some research and started reading &lt;a href="https://www.amazon.com/Little-Book-Still-Beats-Market/dp/0470624159" rel="noopener noreferrer"&gt;The Little Book That Still Beats The Market&lt;/a&gt; by Joel Greenblatt. From the book, I found some formulas that could be useful to me when making decisions on whether or not to invest in the stocks of companies in &lt;a href="https://en.wikipedia.org/wiki/Singapore" rel="noopener noreferrer"&gt;Singapore&lt;/a&gt;. This post isn't to promote the book or its investment strategies, but more to showcase the following and how I did it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Interacting with Firestore through Python&lt;/li&gt;
&lt;li&gt;Running a Python script at specific time intervals on the Compute Engine&lt;/li&gt;
&lt;li&gt;Using Cloud Functions to retrieve data from Firestore&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At first, I created a Python script for populating a Google Sheet with the financial details and self-calculated ratios from companies listed on the &lt;a href="http://sgx.com/wps/portal/sgxweb/home/!ut/p/a1/04_Sj9CPykssy0xPLMnMz0vMAfGjzOKNHB1NPAycDSz9wwzMDTxD_Z2Cg8PCDANdjYEKIoEKDHAARwNC-sP1o8BK8JhQkBthkO6oqAgAzDYPQQ!!/dl5/d5/L2dBISEvZ0FBIS9nQSEh/" rel="noopener noreferrer"&gt;Singapore Exchange website&lt;/a&gt;. I found this a hassle as I had to do run the Python script everyday to get the updated prices of the stocks. I then decided to move this everyday process to the Google Cloud Platform so that I no longer have to do the everyday process myself, and leave it to the cloud to do it for me :D&lt;/p&gt;

&lt;p&gt;The following will explain how I did what I did in hopes to help anyone else out there who might want to use the Google Cloud Platform in a similar fashion as I did.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before proceeding any further, I would like to note that the following have to been done first to keep this post short and simple. I have included links to get you started as well.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/resource-manager/docs/creating-managing-projects" rel="noopener noreferrer"&gt;Creating a Google Cloud Platform project&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/iam/docs/creating-managing-service-account-keys#iam-service-account-keys-create-gcloud" rel="noopener noreferrer"&gt;Retrieving service account key&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/compute/docs/instances/create-start-instance" rel="noopener noreferrer"&gt;Creating a Cloud Engine VM Instance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firebase.google.com/docs/functions/get-started" rel="noopener noreferrer"&gt;Setting Up Firebase Cloud Functions&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2F0Hu_uP6l37EDMuwCmPb1Ty3NMX9RlGdBB6qU-ne03OdwwXrshRTe6mNd5BeHqyQL7uLTeKtcuc9COVvv75MA%3Dw1920-h920" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2F0Hu_uP6l37EDMuwCmPb1Ty3NMX9RlGdBB6qU-ne03OdwwXrshRTe6mNd5BeHqyQL7uLTeKtcuc9COVvv75MA%3Dw1920-h920" alt="Overview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the above diagram, the only thing I have to do is to make a GET request through the Cloud Functions HTTP API which will return all the already calculated formulas and values stored in the Firestore. Essentially, steps 1, 2 and 3 involve the Python script I have created. Steps 1 and 2 are done simply by using the &lt;a href="http://docs.python-requests.org/en/master/" rel="noopener noreferrer"&gt;Requests library&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Interacting with Firestore through Python&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Firestore uses the concept of collections, documents and fields to store the data you want it to. So for instance, using the analogy of a book library, if you have a shelf of books, that is a collection in Firestore's viewpoint. The books themselves are documents, and each page in the book is a field on its own. Each document can have its own collection as well, but I will not get into that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shelf [collection]
|--book1 [document]
  |-- page1 [field]
  |-- page2 [field]
|--book2 [document]
  |-- page1 [field]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To interact and update data on the Cloud Firestore from your Python script, you first have to install the Google Cloud Firestore library via &lt;code&gt;pip install google-cloud-firestore&lt;/code&gt;.  The following is the code snippet to initialize Firestore with your service account key that you have previously retrieved.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.cloud&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;firestore&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_service_account_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/path/to/service/key&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well that is it actually! To write data to Firestore, simply do the following:&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;doc_ref&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name_of_collection&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;u&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name_of_document&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;doc_ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_to_update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;data_to_update&lt;/code&gt; is a Python dictionary which holds the keys and respective values you would want the Firestore document to hold. The &lt;code&gt;.set()&lt;/code&gt; allows you to update or insert new fields into the document. For myself, I was putting the company name, stock prices, financial ratios and other fields here. &lt;/p&gt;

&lt;p&gt;A point to note here is that even if the document or collection does not exist yet, &lt;code&gt;.set()&lt;/code&gt; function automatically creates the collection and document for you and populates the document with the fields as mentioned before.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Running a Python script on Compute Engine&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;There are a few ways of pushing your Python script to your VM Instance. How I did it was to create a repository in my Google Cloud project and pushed it there. The reason I created the repository was because I still wanted some form of version control as, knowing myself, I like to make changes and explore different ways to do things in my code and end up confusing myself in the end. Even though it is a small project, I felt it was a good practice for me personally. I then remotely accessed the VM Instance via SSH and cloned the repository into the instance.&lt;/p&gt;

&lt;p&gt;Now for the scheduling of the Python script. Initially, I thought calling the Python script every 30 minutes was a good idea. However, after some consideration, I felt scheduling the script to run at 6pm (GMT +0800) was the ideal case because the Singapore Exchange opens at 9am and closes at 5pm, and I really only have time to view the stock prices after work anyway.&lt;/p&gt;

&lt;p&gt;To schedule your Python script to run either at certain time intervals or at specific timings, you can use Cron jobs as I did. In the SSH session of your VM Instance, edit your user's Crontab using the &lt;code&gt;crontab -e&lt;/code&gt; command. At the end of the file, at your schedules in the following format&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# m h  dom mon dow   command
0 10 * * 1-5 cd /path/to/python/folder &amp;amp;&amp;amp; python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above snippet runs the Python script at 10am UTC (aka 6pm SGT), every weekday of the day, indicated by the &lt;code&gt;1-5&lt;/code&gt; segment. If you would like your script to run after every time interval, you can do the following instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Runs the command every hour at the 0th minute
0 */1 * * * &amp;lt;some command&amp;gt;

# Runs the command at the 0th minute every day
0 * */1 * * &amp;lt;some command&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: A mistake that I made during my first few times using Crontab in the VM Instance is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Runs the command every minute after every hour
* */1 * * * &amp;lt;some command&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My intention was to run it at every hour. But I missed the &lt;code&gt;0&lt;/code&gt; at the minute mark of the cron job. So it was running the script at &lt;strong&gt;EVERY MINUTE AFTER EVERY HOUR.&lt;/strong&gt; My script was taking around 3 minutes to run each time it was called. I did not mind the relatively long run time. However, since the script is being run every minute, and each takes 3 minutes to complete... Well, you can do the math. And silly me was trying to figure out why the CPU usage on my VM Instance was constantly at 150-200% and I could not even access it via SSH. That was a funny lesson :P&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Using Cloud Functions to retrieve data from Firestore&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For this step, I linked the Google Cloud project to Firebase. The reason I did this was for possible future versions in which I could host a website on Firebase Hosting, which taps on the data from the Cloud Firestore, allowing anyone to view the financial details at a glance. Another reason is also because I am much more familiar with Firebase and the requirements for Cloud Functions there.&lt;/p&gt;

&lt;p&gt;I installed Express.js into my Cloud Functions folder via &lt;code&gt;npm install --save express&lt;/code&gt;. Express.js allows me to easily create web APIs as I needed multiple end-points for retrieving various company information from the Firestore I have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt;  &lt;span class="nx"&gt;express&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;  &lt;span class="nx"&gt;app&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:nameOfDocument&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt;  &lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt;  &lt;span class="nx"&gt;firestoreRef&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name_of_collection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;firestoreRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt;  &lt;span class="nx"&gt;returnObj&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnObj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid document name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;errorObject&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Internal Server Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a step by step explanation of what is happening is the snippet above. Firstly, access to Firestore is initialized by &lt;code&gt;var db = admin.firestore();&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:nameOfDocument&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above tells the Express that we would like to create a GET request with the &lt;code&gt;'/:nameOfDocument'&lt;/code&gt; end-point, where &lt;code&gt;:nameOfDocument&lt;/code&gt; is a parameter in the URL. &lt;code&gt;req&lt;/code&gt; and &lt;code&gt;res&lt;/code&gt; are request and response objects which are received and going to be sent respectively. Currently, only the &lt;code&gt;res&lt;/code&gt; is being used, but more on that later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nameOfDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line takes the parameter from the URL, that is &lt;code&gt;:nameOfDocument&lt;/code&gt; in this case, and stores it as a variable called &lt;code&gt;nameOfDocument&lt;/code&gt;, which will be used in the next line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;firestoreRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name_of_collection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line essentially creates a reference to the document &lt;code&gt;nameOfDocument&lt;/code&gt;. The collection name is currently not a variable. You can also use include the name of collection as a parameter as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/:nameOfCollection/:nameOfDocument&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nameOfDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nameOfCollection&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameOfCollection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;firestoreRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameOfCollection&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameOfDocument&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you can specify it in the URL without having to alter the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;firestoreRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;returnObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnObj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above segment takes the reference mentioned earlier and checks if it exists. This is essential as a user might accidentally type a wrong document or collection name, and we would want to return the appropriate response. &lt;code&gt;snapshot.data()&lt;/code&gt; retrieves all the field key-value pairs and puts it in the object called &lt;code&gt;returnObj&lt;/code&gt; We then return this as a JSON object with a status code of 200.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line tells Cloud Functions that when a request is made to &lt;code&gt;&amp;lt;cloudfunctions.net url&amp;gt;/api&lt;/code&gt; should be passed to the Express object called &lt;code&gt;app&lt;/code&gt; and handled accordingly based on the end-points specified in the &lt;code&gt;app&lt;/code&gt; object itself.&lt;/p&gt;

&lt;p&gt;And that is it! You can now call your Cloud Functions from the link provided on the Firebase Cloud Functions page which will retrieve the relevant data that you want to work on from your Firestore.&lt;/p&gt;

&lt;p&gt;P.S. This is my first tutorial/personal experience post. Kindly do let me know what can be improved and how I can be a better programmer as well. All constructive feedback are welcome. Thank you for reading through my post! :D &lt;/p&gt;

</description>
      <category>python</category>
      <category>javascript</category>
      <category>firebase</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What is YOUR ultimate goal that you want to achieve as a developer?</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Wed, 15 Aug 2018 04:09:52 +0000</pubDate>
      <link>https://forem.com/dansyuqri/what-is-your-ultimate-goal-in-the-path-of-a-developer-4e44</link>
      <guid>https://forem.com/dansyuqri/what-is-your-ultimate-goal-in-the-path-of-a-developer-4e44</guid>
      <description>&lt;p&gt;We all know that the journey of a developer is one that requires constant learning, no matter how long you have been on the road. However, what is that one thing that you want to achieve, and when you do achieve it, you can sit back and say, "Ahhh.. I have finally fulfilled my purpose as a developer!" &lt;/p&gt;

&lt;p&gt;(It can be directly or indirectly related to being a developer)&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>goals</category>
      <category>life</category>
    </item>
    <item>
      <title>How did you get out of the habit of copying/pasting code?</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Fri, 29 Jun 2018 14:13:14 +0000</pubDate>
      <link>https://forem.com/dansyuqri/how-did-you-get-out-of-the-habit-of-copyingpasting-code-3bk5</link>
      <guid>https://forem.com/dansyuqri/how-did-you-get-out-of-the-habit-of-copyingpasting-code-3bk5</guid>
      <description>&lt;p&gt;Like the title describes, I would like to know how you got out of the (bad) habit, particularly when it saves time and does the job.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>general</category>
      <category>habits</category>
    </item>
    <item>
      <title>Is being a master Android developer feasible today considering the availability of UI frameworks such as Flutter, React etc.?</title>
      <dc:creator>Muhammad Syuqri</dc:creator>
      <pubDate>Wed, 28 Feb 2018 09:12:45 +0000</pubDate>
      <link>https://forem.com/dansyuqri/is-being-a-master-android-developer-feasible-today-considering-the-availability-of-ui-frameworks-such-as-flutter-react-etc--5312</link>
      <guid>https://forem.com/dansyuqri/is-being-a-master-android-developer-feasible-today-considering-the-availability-of-ui-frameworks-such-as-flutter-react-etc--5312</guid>
      <description></description>
      <category>discuss</category>
    </item>
  </channel>
</rss>
