<?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>DEV Community: Ryan Lee</title>
    <description>The latest articles on DEV Community by Ryan Lee (@ryanlwh).</description>
    <link>https://dev.to/ryanlwh</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%2F1247775%2F886fe751-015c-4467-b49f-9264078cf01d.jpg</url>
      <title>DEV Community: Ryan Lee</title>
      <link>https://dev.to/ryanlwh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ryanlwh"/>
    <language>en</language>
    <item>
      <title>Python 3.7.2 Installation Error: call to undeclared function 'sendfile'</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Fri, 18 Apr 2025 09:26:41 +0000</pubDate>
      <link>https://dev.to/ryanlwh/python-372-installation-error-call-to-undeclared-function-sendfile-327n</link>
      <guid>https://dev.to/ryanlwh/python-372-installation-error-call-to-undeclared-function-sendfile-327n</guid>
      <description>&lt;p&gt;I had to install Python 3.7.2 to try out a project. Using pyenv, I encountered a "BUILD FAILED" error. The entire error message is below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ pyenv &lt;span class="nb"&gt;install &lt;/span&gt;3.7.2
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Installing Python-3.7.2...
python-build: use tcl-tk from homebrew
python-build: use readline from homebrew
python-build: use zlib from xcode sdk

BUILD FAILED &lt;span class="o"&gt;(&lt;/span&gt;OS X 15.3.2 using python-build 20180424&lt;span class="o"&gt;)&lt;/span&gt;

Inspect or clean up the working tree at /var/folders/k0/wdbl3h8d2z3cc7w39t599q380000gn/T/python-build.20250415175136.65981
Results logged to /var/folders/k0/wdbl3h8d2z3cc7w39t599q380000gn/T/python-build.20250415175136.65981.log

Last 10 log lines:
      |                                                      ^
clang &lt;span class="nt"&gt;-Wno-unused-result&lt;/span&gt; &lt;span class="nt"&gt;-Wsign-compare&lt;/span&gt; &lt;span class="nt"&gt;-Wunreachable-code&lt;/span&gt; &lt;span class="nt"&gt;-DNDEBUG&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fwrapv&lt;/span&gt; &lt;span class="nt"&gt;-O3&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt;    &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c99 &lt;span class="nt"&gt;-Wextra&lt;/span&gt; &lt;span class="nt"&gt;-Wno-unused-result&lt;/span&gt; &lt;span class="nt"&gt;-Wno-unused-parameter&lt;/span&gt; &lt;span class="nt"&gt;-Wno-missing-field-initializers&lt;/span&gt; &lt;span class="nt"&gt;-Wno-cast-function-type&lt;/span&gt; &lt;span class="nt"&gt;-Werror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;implicit-function-declaration   &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;./Include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Users/ryanlee/.pyenv/versions/3.7.2/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Users/ryanlee/.pyenv/versions/3.7.2/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include  &lt;span class="nt"&gt;-DPy_BUILD_CORE_BUILTIN&lt;/span&gt;  &lt;span class="nt"&gt;-c&lt;/span&gt; ./Modules/errnomodule.c &lt;span class="nt"&gt;-o&lt;/span&gt; Modules/errnomodule.o
./Modules/posixmodule.c:8409:15: error: call to undeclared &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="s1"&gt;'sendfile'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; ISO C99 and later &lt;span class="k"&gt;do &lt;/span&gt;not support implicit &lt;span class="k"&gt;function &lt;/span&gt;declarations &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;-Wimplicit-function-declaration&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
 8409 |         ret &lt;span class="o"&gt;=&lt;/span&gt; sendfile&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;, out, offset, &amp;amp;sbytes, &amp;amp;sf, flags&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      |               ^
clang &lt;span class="nt"&gt;-Wno-unused-result&lt;/span&gt; &lt;span class="nt"&gt;-Wsign-compare&lt;/span&gt; &lt;span class="nt"&gt;-Wunreachable-code&lt;/span&gt; &lt;span class="nt"&gt;-DNDEBUG&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="nt"&gt;-fwrapv&lt;/span&gt; &lt;span class="nt"&gt;-O3&lt;/span&gt; &lt;span class="nt"&gt;-Wall&lt;/span&gt;    &lt;span class="nt"&gt;-std&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;c99 &lt;span class="nt"&gt;-Wextra&lt;/span&gt; &lt;span class="nt"&gt;-Wno-unused-result&lt;/span&gt; &lt;span class="nt"&gt;-Wno-unused-parameter&lt;/span&gt; &lt;span class="nt"&gt;-Wno-missing-field-initializers&lt;/span&gt; &lt;span class="nt"&gt;-Wno-cast-function-type&lt;/span&gt; &lt;span class="nt"&gt;-Werror&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;implicit-function-declaration   &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt;./Include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Users/ryanlee/.pyenv/versions/3.7.2/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/usr/local/opt/readline/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Users/ryanlee/.pyenv/versions/3.7.2/include &lt;span class="nt"&gt;-I&lt;/span&gt;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include  &lt;span class="nt"&gt;-DPy_BUILD_CORE_BUILTIN&lt;/span&gt;  &lt;span class="nt"&gt;-c&lt;/span&gt; ./Modules/pwdmodule.c &lt;span class="nt"&gt;-o&lt;/span&gt; Modules/pwdmodule.o
1 error generated.
1 warning generated.
make: &lt;span class="k"&gt;***&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Modules/posixmodule.o] Error 1
make: &lt;span class="k"&gt;***&lt;/span&gt; Waiting &lt;span class="k"&gt;for &lt;/span&gt;unfinished jobs....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After some digging around, I found a workaround for 3.7.3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xcrun &lt;span class="nt"&gt;--show-sdk-path&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/usr/include"&lt;/span&gt; &lt;span class="nv"&gt;LDFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; zlib&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib"&lt;/span&gt; pyenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--patch&lt;/span&gt; 3.7.3 &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I figured it might work for 3.7.2. After adapting the command, I got a "zsh: no matches found" error:&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;&lt;/span&gt; &lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xcrun &lt;span class="nt"&gt;--show-sdk-path&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/usr/include"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;LDFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; zlib&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  pyenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--patch&lt;/span&gt; 3.7.2 &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://github.com/python/cpython/commit/8ea6353.patch?full_index&lt;span class="o"&gt;=&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;
zsh: no matches found: https://github.com/python/cpython/commit/8ea6353.patch?full_index&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Googling on this error, it turns out that the "?" from the GitHub URI is tripping up the shell interpreter. So we should add a quote around the URI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sSL 'https://github.com/python/cpython/commit/8ea6353.patch?full_index=1'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xcrun &lt;span class="nt"&gt;--show-sdk-path&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/usr/include"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;LDFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; zlib&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  pyenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--patch&lt;/span&gt; 3.7.2 &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; &lt;span class="s1"&gt;'https://github.com/python/cpython/commit/8ea6353.patch?full_index=1'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it worked!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;❯ &lt;span class="nv"&gt;CFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/include -I&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xcrun &lt;span class="nt"&gt;--show-sdk-path&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/usr/include"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nv"&gt;LDFLAGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; openssl&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; readline&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; zlib&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib -L&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;brew &lt;span class="nt"&gt;--prefix&lt;/span&gt; bzip2&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/lib"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  pyenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--patch&lt;/span&gt; 3.7.2 &amp;lt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; &lt;span class="s1"&gt;'https://github.com/python/cpython/commit/8ea6353.patch?full_index=1'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Installing Python-3.7.2...
patching file &lt;span class="s1"&gt;'Misc/NEWS.d/next/macOS/2020-06-24-13-51-57.bpo-41100.mcHdc5.rst'&lt;/span&gt;
patching file configure
patching file configure.ac
python-build: use tcl-tk from homebrew
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.7.2 to /Users/ryanlee/.pyenv/versions/3.7.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gonkunblog.com/en/python-3-7-3-install-error/2492/" rel="noopener noreferrer"&gt;https://gonkunblog.com/en/python-3-7-3-install-error/2492/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/zsh/comments/h9mdvc/why_do_i_get_this_error_zsh_no_matches_found/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/zsh/comments/h9mdvc/why_do_i_get_this_error_zsh_no_matches_found/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>pyenv</category>
    </item>
    <item>
      <title>Don't Miss Out - Amazon EC2 T4g Free Trial Extended to 2025</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Fri, 20 Dec 2024 07:49:22 +0000</pubDate>
      <link>https://dev.to/ryanlwh/amazon-ec2-t4g-free-trial-extended-yet-again-1ba3</link>
      <guid>https://dev.to/ryanlwh/amazon-ec2-t4g-free-trial-extended-yet-again-1ba3</guid>
      <description>&lt;p&gt;Time flies. It's the end of the year again! &lt;/p&gt;

&lt;p&gt;I have been running the EC2 t4g.small instance since 2022 to take advantage of the free trial, which has since been extended twice to December 31, 2024. Yesterday, I went to check the official website of the &lt;a href="https://aws.amazon.com/ec2/instance-types/t4/" rel="noopener noreferrer"&gt;EC2 T4g Instances&lt;/a&gt; to confirm the end date of the trial in preparation for purchasing a savings plan. To my surprise, they have changed the trial end year to 2025! How generous!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Free Trial: Try Amazon EC2 t4g.small instances powered by AWS Graviton2 processors free for up to 750 hours / month until Dec 31st 2025. Refer to the &lt;a href="https://aws.amazon.com/ec2/faqs/#t4g-instances" rel="noopener noreferrer"&gt;FAQ&lt;/a&gt; for additional details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best part of this free trial is that, &lt;em&gt;all existing and new customers&lt;/em&gt; can take advantage of it, and it is &lt;em&gt;available in addition to free tiers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;There we go. A Christmas present from AWS again.&lt;/p&gt;

&lt;h1&gt;
  
  
  Who is eligible for the free trial?
&lt;/h1&gt;

&lt;p&gt;As mentioned in the &lt;a href="https://aws.amazon.com/ec2/faqs/#t4g-instances" rel="noopener noreferrer"&gt;FAQ&lt;/a&gt;, all existing and new customers are eligible. However, if you have signed up for consolidated billing, you will have access to one free trial per Organization.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to join the free trial?
&lt;/h1&gt;

&lt;p&gt;It's as easy as spinning up a t4g.small instance. The bill will take care of itself. It will appear as a $0 item under On-Demand pricing.&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>One Byte Explainer: Caesar Cipher</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Sun, 23 Jun 2024 05:59:50 +0000</pubDate>
      <link>https://dev.to/ryanlwh/one-byte-explainer-caesar-cipher-cg0</link>
      <guid>https://dev.to/ryanlwh/one-byte-explainer-caesar-cipher-cg0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/cs"&gt;DEV Computer Science Challenge v24.06.12: One Byte Explainer&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explainer
&lt;/h2&gt;

&lt;p&gt;Caesar Cipher, or shift cipher, is an encryption technique in which each letter in the given text is replaced by a letter some fixed number of positions (e.g. 3) down the alphabet. Can you decode the following message with this method?&lt;/p&gt;

&lt;p&gt;rqh ebwh hasodlqhu&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cschallenge</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Learn to be Pythonic: List of Multiples of 3</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Mon, 26 Feb 2024 06:59:14 +0000</pubDate>
      <link>https://dev.to/ryanlwh/learn-to-be-pythonic-list-of-multiples-of-3-4b63</link>
      <guid>https://dev.to/ryanlwh/learn-to-be-pythonic-list-of-multiples-of-3-4b63</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;One of the best ways to learn a programming language is by solving the same challenge with different approaches. Learning to be more &lt;a href="https://en.wiktionary.org/wiki/Pythonic#English"&gt;Pythonic&lt;/a&gt; is no exception. We will solve simple Python programming challenges going from naive and straightforward ways to more Pythonic and smarter approaches. By doing so, we can gain a deeper understanding of what Python offers out of the box and appreciate the flexibility of this beautiful language.&lt;/p&gt;

&lt;h1&gt;
  
  
  Problem Statement
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a list of multiples of 3 from 0 to 15 (inclusive)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Solutions
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Brute Force
&lt;/h2&gt;

&lt;p&gt;The simplest solution (almost like cheating) is just initializing a list with multiples of 3.&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;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  While Loop with Break
&lt;/h2&gt;

&lt;p&gt;Observing the problem statement, we induced that we can go through each integer &lt;code&gt;i&lt;/code&gt; from 0 to 15, and check whether it is a multiple of 3 (&lt;code&gt;i % 3 == 0&lt;/code&gt;). A naive implementation is to use an infinite loop (&lt;code&gt;while True&lt;/code&gt;) and &lt;code&gt;break&lt;/code&gt; out when &lt;code&gt;i&lt;/code&gt; is greater than 15.&lt;/p&gt;

&lt;p&gt;(This is inspired by a Python quiz question.)&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;while&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;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  While Loop with Condition
&lt;/h2&gt;

&lt;p&gt;A slight improvement to the above solution is to make use of the condition of the &lt;code&gt;while&lt;/code&gt; loop: loop whenever &lt;code&gt;i &amp;lt; N + 1&lt;/code&gt;.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  While Loop Incremented by Steps
&lt;/h2&gt;

&lt;p&gt;You may have observed that, for this particular challenge, we can reduce the number of steps by incrementing &lt;code&gt;i&lt;/code&gt; by 3. This also eliminates the check for modulo 3.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  For Loop
&lt;/h2&gt;

&lt;p&gt;In fundamental computer science, when the number of iterations is known in advance, a &lt;code&gt;for&lt;/code&gt; loop is more appropriate. A very useful iterator in Python for this use case is &lt;code&gt;range&lt;/code&gt;.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&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;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is cleaner and more expressive than the &lt;code&gt;while&lt;/code&gt; loop.&lt;/p&gt;

&lt;h2&gt;
  
  
  List Comprehension
&lt;/h2&gt;

&lt;p&gt;To further refactor the solution, we turn to a feature of Python called “&lt;a href="https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions"&gt;list comprehension&lt;/a&gt;”. It provides a concise way to create a list from an iterator. This is when the solution starts to be more “Pythonic”.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Filter
&lt;/h2&gt;

&lt;p&gt;An alternative solution without the &lt;code&gt;for&lt;/code&gt; loop is using the &lt;code&gt;filter&lt;/code&gt; function. It is handy for filtering an iterator through a test function. In this example, the test function is constructed with &lt;code&gt;lambda&lt;/code&gt;.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Filter with Predefined Function
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;lambda&lt;/code&gt; function is convenient but lacks context and compromises readability. A better version of the &lt;code&gt;filter&lt;/code&gt; solution is to predefine the test function.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_mul_3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_mul_3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Range with Steps
&lt;/h2&gt;

&lt;p&gt;In a previous solution, we optimized the loop by reducing the number of iterations by incrementing the counter by a step of 3. This is possible with the &lt;code&gt;range&lt;/code&gt; function by taking advantage of its optional third argument, &lt;code&gt;step&lt;/code&gt;. It tells &lt;code&gt;range&lt;/code&gt; to increment the counter by the &lt;code&gt;step&lt;/code&gt; amount. As such, we can remove the &lt;code&gt;filter&lt;/code&gt; altogether.&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;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;

&lt;span class="n"&gt;ans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;By finding different ways to solve a simple problem, we have already touched on the key Python concepts of &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, &lt;code&gt;break&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;range&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;lambda&lt;/code&gt;, and list comprehension. The earlier solutions are more naive and not recommended as &lt;a href="https://peps.python.org/pep-0020/"&gt;best practices&lt;/a&gt;, but they are still good exercises to solidify the fundamentals. Between the more Pythonic list comprehension and functional style, it will require an experienced programmer to weigh the pros and cons to balance readability, efficiency, and maintainability. Lastly, using the step argument from range might seem obvious, but it requires deeper knowledge of Python and may confuse peer programmers trying to maintain the code. Therefore, it is essential for a programmer to share his or her knowledge with others, so that the team can grow as a whole, thereby increasing the efficiency (or Pythonicity?) of a software project.&lt;/p&gt;

&lt;p&gt;Can you find other creative ways to solve this challenge?&lt;/p&gt;




&lt;h1&gt;
  
  
  Further resources:
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://pythonguides.com/python-for-loop-index/"&gt;Python For Loop With Index&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://realpython.com/list-comprehension-python/"&gt;When to Use a List Comprehension in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.python.org/3/tutorial/index.html"&gt;The Python Tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewars.com"&gt;Codewars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leetcode.com"&gt;LeetCode&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Migrating Amazon SNS from Legacy FCM API to HTTP V1 API</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Tue, 23 Jan 2024 09:50:04 +0000</pubDate>
      <link>https://dev.to/ryanlwh/migrating-amazon-sns-from-legacy-fcm-api-to-http-v1-api-onf</link>
      <guid>https://dev.to/ryanlwh/migrating-amazon-sns-from-legacy-fcm-api-to-http-v1-api-onf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;On a work project, we use Amazon SNS to send push notifications to a mobile app registered with Google's Firebase Cloud Messaging (FCM). Although Google was deprecating the Legacy FCM API at that time, SNS did not yet support the new HTTP V1 API. Last weekend, I received an email from AWS that &lt;a href="https://aws.amazon.com/about-aws/whats-new/2024/01/amazon-sns-fcm-http-v1-api-mobile-notifications/" rel="noopener noreferrer"&gt;SNS now supports the new API&lt;/a&gt; (yay!). &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllzvzgvifjqbccmew3tp.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllzvzgvifjqbccmew3tp.png" alt="Screenshot of the email"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Procedures
&lt;/h2&gt;

&lt;p&gt;This tutorial is written based on the steps I took to migrate to the V1 API. Please adjust accordingly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Getting the Service JSON&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to the &lt;a href="https://console.firebase.google.com/" rel="noopener noreferrer"&gt;Firebase console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Select the project that receives API calls from SNS.&lt;/li&gt;
&lt;li&gt;At the top left corner, click on the gear icon, and select &lt;strong&gt;Project Settings&lt;/strong&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-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb5lrhq6g9gj01qfh61bz.png" alt="Project Settings"&gt;
&lt;/li&gt;
&lt;li&gt;At the top navigation under Project Settings, pick &lt;strong&gt;Service accounts&lt;/strong&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-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f1imu7tmnclrqnlbv95.png" alt="Service accounts"&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Generate new private key&lt;/strong&gt;. A popup shows up reminding you to secure the key. Click *&lt;em&gt;Generate key&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;The key should be downloaded.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Uploading the Service JSON&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to the &lt;a href="https://console.aws.amazon.com/sns" rel="noopener noreferrer"&gt;Amazon SNS console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Push notifications&lt;/strong&gt; (under &lt;em&gt;Mobile&lt;/em&gt;) from the left side menu. Pick the appropriate platform application.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs2hf06gk5cjb2x08q9oc.png" alt="Push notifications"&gt;
&lt;/li&gt;
&lt;li&gt;Edit the platform application. At the authentication method, pick &lt;strong&gt;Token (recommended)&lt;/strong&gt;. It will ask you to upload a service.json file. Pick the key downloaded previously from the Firebase console.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Falnv9zv1eheqlzodb26o.png" alt="Token authentication method"&gt;
&lt;/li&gt;
&lt;li&gt;Save changes.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;At the Platform application page, click on the link of an endpoint from the list below. At the top right-hand corner, click &lt;strong&gt;Publish message&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;At the &lt;strong&gt;Message body&lt;/strong&gt; section, pick Custom payload and input the GCM message payload according to your platform (mine is Android).
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jxpt0xvt6felgbmafh6.png" alt="Message body and custom payload"&gt;
&lt;/li&gt;
&lt;li&gt;Check the app for notifications.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9was9s4xq73vd8vetuan.png" alt="Push notification received"&gt;
&lt;/li&gt;
&lt;li&gt;To verify that it is using the new API, go back to the Firebase console &lt;strong&gt;Service accounts&lt;/strong&gt; tab (refer to step 1.4). Click &lt;strong&gt;Manage service account permissions&lt;/strong&gt; at the top-right-hand corner.&lt;/li&gt;
&lt;li&gt;At the Service accounts management page, locate the account associated with Firebase Admin SDK. Click the dots menu under &lt;strong&gt;Action&lt;/strong&gt; on the right, and pick &lt;strong&gt;View metrics&lt;/strong&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-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1j38ws7gosf1g2mwjlwz.png" alt="View metrics"&gt;
&lt;/li&gt;
&lt;li&gt;Verify there were actions when the message was being sent.
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sxrptowjrthmibz1wqm.png" alt="Metrics"&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;h2&gt;
  
  
  Congratulations!
&lt;/h2&gt;

&lt;p&gt;The migration is now complete. You may have to &lt;a href="https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=en&amp;amp;authuser=0#update-the-payload-of-send-requests" rel="noopener noreferrer"&gt;update the message payload&lt;/a&gt; to the new message format. Start exploring the multiplatform messaging capability now!&lt;/p&gt;




&lt;h2&gt;
  
  
  Extended reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://stackoverflow.com/questions/56659260/what-service-account-permissions-are-required-for-firebase-cloud-messaging-on-ap" rel="noopener noreferrer"&gt;What service account permissions are required for firebase cloud messaging on app engine?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=en&amp;amp;authuser=0" rel="noopener noreferrer"&gt;Migrate from legacy FCM APIs to HTTP v1&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>sns</category>
      <category>firebase</category>
      <category>google</category>
    </item>
    <item>
      <title>AWS Boto3: Clients vs Resources - Amazon DynamoDB</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Sun, 21 Jan 2024 09:44:48 +0000</pubDate>
      <link>https://dev.to/ryanlwh/aws-boto3-clients-vs-resources-dynamodb-10f</link>
      <guid>https://dev.to/ryanlwh/aws-boto3-clients-vs-resources-dynamodb-10f</guid>
      <description>&lt;p&gt;Recently, my colleague brought up the difficulty of using the &lt;a href="https://aws.amazon.com/sdk-for-python/" rel="noopener noreferrer"&gt;AWS SDK for Python (Boto3)&lt;/a&gt; while working with DynamoDB, especially the cumbersome mapping of &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html" rel="noopener noreferrer"&gt;&lt;code&gt;AttributeValue&lt;/code&gt;&lt;/a&gt; objects on the &lt;code&gt;Table&lt;/code&gt; operations. One of the easiest ways to get around this difficulty is to switch from the &lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html" rel="noopener noreferrer"&gt;clients&lt;/a&gt; interface to the &lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html" rel="noopener noreferrer"&gt;resources&lt;/a&gt; interface.&lt;/p&gt;

&lt;p&gt;It is important to know the key difference between clients and resources. From the definition of the Boto3 documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Clients provide a low-level interface to AWS whose methods map close to 1:1 with service APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
&lt;p&gt;Resources represent an object-oriented interface to Amazon Web Services (AWS). They provide a higher-level abstraction than the raw, low-level calls made by service clients.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's quickly write a script to demonstrate the difference in the responses:&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;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;simplejson&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Items&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;items_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;simplejson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items_json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ddb_table_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# DynamoDB client
&lt;/span&gt;&lt;span class="n"&gt;ddb_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dynamodb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Scan the table
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ddb_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TableName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ddb_table_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;client&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# DynamoDB resource
&lt;/span&gt;&lt;span class="n"&gt;ddb_resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dynamodb&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Scan the table
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ddb_resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ddb_table_name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resource&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;client:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"datetime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"S"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-01-20T00:01:02"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"N"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"L"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"M"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                            &lt;/span&gt;&lt;span class="nl"&gt;"N"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"40"&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"M"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                            &lt;/span&gt;&lt;span class="nl"&gt;"N"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"56"&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="err"&gt;resource:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"datetime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-01-20T00:01:02"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;56&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the simplicity of the second output. The abstraction of the resources interface deserialized the low-level raw response of the AWS service API.&lt;/p&gt;

&lt;p&gt;In most cases, the resources interface can be used over the low-level clients for the abstraction benefits. However, as stated at the top of the resources interface documentation: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The AWS Python SDK team does not intend to add new features to the resources interface in boto3". &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Therefore, it is essential to compare both interfaces to determine whether the resources interface is sufficient for your use case.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a future post, I will explore another method to work with the AttributeValue maps in Boto3.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html" rel="noopener noreferrer"&gt;DynamoDB - Boto3 1.34.23 documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href="https://github.com/boto/boto3/discussions/3563" rel="noopener noreferrer"&gt;More info about resource deprecation? · boto/boto3 · Discussion #3563&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.org/project/simplejson/" rel="noopener noreferrer"&gt;simplejson · PyPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hands-on.cloud/boto3/client-vs-resource/" rel="noopener noreferrer"&gt;Boto3 Client vs. Resource&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>dynamodb</category>
    </item>
    <item>
      <title>Fixing MSVCP140_ATOMIC_WAIT.dll Not Found</title>
      <dc:creator>Ryan Lee</dc:creator>
      <pubDate>Wed, 17 Jan 2024 06:10:18 +0000</pubDate>
      <link>https://dev.to/ryanlwh/msvcp140atomicwaitdll-not-found-11kh</link>
      <guid>https://dev.to/ryanlwh/msvcp140atomicwaitdll-not-found-11kh</guid>
      <description>&lt;p&gt;One of my colleagues recently encountered an error trying to open an Excel workbook on Sharepoint via the "&lt;a href="https://support.microsoft.com/en-us/office/work-in-excel-for-the-web-812f519f-8db1-4de2-81d2-d7f3510168ca#:~:text=Select%20Open%20in%20Desktop%20App,select%20Open%20in%20Desktop%20App." rel="noopener noreferrer"&gt;Open in Desktop App&lt;/a&gt;" button. The screenshot of the error is below: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8wkkomsjfmbm4h57nrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8wkkomsjfmbm4h57nrs.png" alt="Image description" width="513" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The error wasn't triggered when starting Excel normally, nor opening the same spreadsheet from OneDrive Desktop.&lt;/p&gt;

&lt;p&gt;Upon Googling, I found results offering the direct download of this DLL, but I am not downloading DLLs from unknown sources! Other search results relate to gaming. One of the results suggested repairing Visual C++, but that didn't help.&lt;/p&gt;

&lt;p&gt;Frustrated, I tried to repair and update a few Microsoft software. It was finally fixed by repairing Microsoft Office.&lt;/p&gt;

&lt;h1&gt;
  
  
  Lesson Learned
&lt;/h1&gt;

&lt;p&gt;In conclusion, if I tried the fix suggested by the error message before searching the web for solutions, I would have saved time and frustration.&lt;/p&gt;




&lt;h3&gt;
  
  
  Extended reading
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.reddit.com/r/Xcom/comments/osgaal/msvcp140_atomic_waitdll_was_not_found/" rel="noopener noreferrer"&gt;https://www.reddit.com/r/Xcom/comments/osgaal/msvcp140_atomic_waitdll_was_not_found/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>windows</category>
      <category>office</category>
      <category>dll</category>
    </item>
  </channel>
</rss>
