<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Import | Haobin Tan</title><link>https://haobin-tan.netlify.app/tags/import/</link><atom:link href="https://haobin-tan.netlify.app/tags/import/index.xml" rel="self" type="application/rss+xml"/><description>Import</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Sat, 11 Feb 2023 00:00:00 +0000</lastBuildDate><image><url>https://haobin-tan.netlify.app/media/icon_hu7d15bc7db65c8eaf7a4f66f5447d0b42_15095_512x512_fill_lanczos_center_3.png</url><title>Import</title><link>https://haobin-tan.netlify.app/tags/import/</link></image><item><title>Import</title><link>https://haobin-tan.netlify.app/docs/coding/python/py-basics/import/</link><pubDate>Sat, 11 Feb 2023 00:00:00 +0000</pubDate><guid>https://haobin-tan.netlify.app/docs/coding/python/py-basics/import/</guid><description>&lt;p>In Python, we use the &lt;strong>&lt;code>import&lt;/code>&lt;/strong> keyword to make code in one &lt;strong>module&lt;/strong> available in another.&lt;/p>
&lt;p>&lt;span style="color: ForestGreen">Imports in Python are important for &lt;strong>structuring your code&lt;/strong> effectively. Using imports properly will make you more productive, allowing you to reuse code while keeping your projects maintainable.&lt;/span>&lt;/p>
&lt;h2 id="basic-python-import">Basic Python Import&lt;/h2>
&lt;h3 id="modules-and-packages">Modules and packages&lt;/h3>
&lt;h4 id="module">Module&lt;/h4>
&lt;ul>
&lt;li>
&lt;p>Definition (according to &lt;a href="https://docs.python.org/glossary.html">Python.org glossary&lt;/a>)&lt;/p>
&lt;blockquote>
&lt;p>An object that serves as an organizational unit of Python code. Modules have a namespace containing arbitrary Python objects. Modules are loaded into Python by the process of importing. (&lt;a href="https://docs.python.org/glossary.html#term-module">Source&lt;/a>)&lt;/p>
&lt;/blockquote>
&lt;/li>
&lt;li>
&lt;p>Usually corresponds to one &lt;code>.py&lt;/code> file containing Python code&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Example&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span> &lt;span class="c1"># import the code in the `math` module&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span> &lt;span class="c1"># access the `pi` variable within the math module&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mf">3.141592653589793&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Acts as a &lt;a href="https://realpython.com/python-namespaces-scope/">&lt;strong>namespace&lt;/strong>&lt;/a> that keeps all the attributes of the module together.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>List the content of a namespace with &lt;code>dir()&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="nb">dir&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># shows what’s in the global namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;__annotations__&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;__builtins__&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">...&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;math&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="nb">dir&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">math&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># shows what&amp;#39;s in the `math` namespace&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;__doc__&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">...&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;nan&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;pi&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;pow&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">...&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Ways to import&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Direct import&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>Import specific parts of a module&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="nn">math&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">pi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">pi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mf">3.141592653589793&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="ne">NameError&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="s1">&amp;#39;math&amp;#39;&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">defined&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this case &lt;code>pi&lt;/code> is placed in the global namespace and NOT within &lt;code>math&lt;/code> namespace.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Rename modules and attributes as they’re imported&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">m&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mf">3.141592653589793&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="nn">math&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">pi&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">PI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">PI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mf">3.141592653589793&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Importing a module both loads the contents and creates a namespace containing the contents.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h4 id="package">Package&lt;/h4>
&lt;ul>
&lt;li>
&lt;p>Definition&lt;/p>
&lt;blockquote>
&lt;p>A Python module which can contain submodules or recursively, subpackages. Technically, a package is a Python module with an &lt;code>__path__&lt;/code> attribute. (&lt;a href="https://docs.python.org/glossary.html#term-package">Source&lt;/a>)&lt;/p>
&lt;/blockquote>
&lt;p>(A package is still a module. As a user, you usually don’t need to worry about whether you’re importing a module or a package.)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>package typically corresponds to a file directory containing Python files and other directories.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>To create a Python package yourself, you create&lt;/p>
&lt;ul>
&lt;li>a directory and&lt;/li>
&lt;li>a &lt;a href="https://docs.python.org/reference/import.html#regular-packages">file named &lt;code>__init__.py&lt;/code>&lt;/a> inside it
&lt;ul>
&lt;li>contains the contents of the package when it’s treated as a module&lt;/li>
&lt;li>can be left empty.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>In general, submodules and subpackages ar NOT imported when you import a package.&lt;/p>
&lt;ul>
&lt;li>You can use &lt;code>__init__.py&lt;/code> to include any or all submodules and subpackages if you want. It’s fairly common to import subpackages and submodules in an &lt;code>__init__.py&lt;/code> file to make them more readily available to your users.&lt;/li>
&lt;li>Submodules and subpackages included in &lt;code>__init__.py&lt;/code> will be then imported along with the package&lt;/li>
&lt;li>Good Example: &lt;a href="https://github.com/psf/requests/blob/v2.23.0/requests/__init__.py#L112">&lt;code>__init__.py&lt;/code> of the &lt;code>request&lt;/code> package&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="absolute-and-relative-imports">Absolute and relative imports&lt;/h3>
&lt;p>Let&amp;rsquo;s say we have a package called &lt;code>world&lt;/code> and it includes a subpackage called &lt;code>africa&lt;/code>.&lt;/p>
&lt;p>In &lt;code>world/__init__.py&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">.&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">africa&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The dot (&lt;code>.&lt;/code>) refers to the current package, and the statement is an example of a &lt;strong>relative import&lt;/strong>. You can read it as &lt;em>“From the current package, import the subpackage &lt;code>africa&lt;/code>.”&lt;/em>&lt;/p>
&lt;p>There’s an equivalent &lt;strong>absolute import&lt;/strong> statement in which you explicitly name the current package:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">world&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">africa&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>The &lt;a href="https://www.python.org/dev/peps/pep-0008/#imports">PEP 8 style guide&lt;/a> recommends using absolute imports in general. However, relative imports are an alternative for organizing package hierarchies.&lt;/strong> (For more information, see &lt;a href="https://realpython.com/absolute-vs-relative-python-imports/">Absolute vs Relative Imports in Python&lt;/a>.)&lt;/p>
&lt;h3 id="pythons-import-path">Python’s import path&lt;/h3>
&lt;p>Python looks for modules and packages in its &lt;a href="https://docs.python.org/glossary.html#term-import-path">&lt;strong>import path&lt;/strong>&lt;/a>, which is a list of locations that are searched for modules to import.&lt;/p>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-primary-100 dark:bg-primary-900">
&lt;span class="pr-3 pt-1 text-primary-600 dark:text-primary-300">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">&lt;p>When you type &lt;code>import &lt;/code>something, Python will look for something a few different places before searching the import path.&lt;/p>
&lt;p>In particular, it’ll look in a module cache to see if something has already been imported, and it’ll search among the built-in modules.&lt;/p>
&lt;/span>
&lt;/div>
&lt;p>You can inspect Python’s import path by printing &lt;code>sys.path&lt;/code>. This list will contain three different kinds of locations:&lt;/p>
&lt;ul>
&lt;li>The directory of the current script (or the current directory if there’s no script, such as when Python is running interactively). This location is always the &lt;strong>first&lt;/strong> in the searching list.&lt;/li>
&lt;li>The contents of the &lt;code>PYTHONPATH&lt;/code> environment variable&lt;/li>
&lt;li>Other, installation-dependent directories&lt;/li>
&lt;/ul>
&lt;p>Python will start at the beginning of the list of locations and look for a given module in each location until the first match.&lt;/p>
&lt;p>You should always be careful that you don’t create modules that &lt;strong>shadow&lt;/strong>, or hide, other important modules.&lt;/p>
&lt;p>For example, we define our custom &lt;code>math&lt;/code> module:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># math.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">double&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">number&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">number&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">double&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">3.14&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mf">6.28&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>But this module also shadows the standard &lt;code>math&lt;/code> module that’s included in the standard library! That means our earlier example of looking up the value of $\pi$ no longer works:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">Traceback&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">most&lt;/span> &lt;span class="n">recent&lt;/span> &lt;span class="n">call&lt;/span> &lt;span class="n">last&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">File&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">line&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">module&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="ne">AttributeError&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">module&lt;/span> &lt;span class="s1">&amp;#39;math&amp;#39;&lt;/span> &lt;span class="n">has&lt;/span> &lt;span class="n">no&lt;/span> &lt;span class="n">attribute&lt;/span> &lt;span class="s1">&amp;#39;pi&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">module&lt;/span> &lt;span class="s1">&amp;#39;math&amp;#39;&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="s1">&amp;#39;math.py&amp;#39;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In other words, Python now searches your new &lt;code>math&lt;/code> module for &lt;code>pi&lt;/code> instead of searching the &lt;code>math&lt;/code> module in the standard library.&lt;/p>
&lt;p>To avoid these kinds of issues, &lt;strong>you should be careful with the names of your modules and packages. In particular, your top-level module and package names should be unique.&lt;/strong>&lt;/p>
&lt;h3 id="namespace-packages">Namespace packages&lt;/h3>
&lt;p>&lt;strong>Namespace packages&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>less dependent on the underlying file hierarchy&lt;/li>
&lt;li>can be split across multiple directories&lt;/li>
&lt;li>A namespace package is created automatically if you have a directory containing a &lt;code>.py&lt;/code> file but no &lt;code>__init__.py&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="import-style-guide">Import style guide&lt;/h3>
&lt;p>&lt;a href="https://www.python.org/dev/peps/pep-0008/">PEP 8&lt;/a>, the Python style guide, has a couple of &lt;a href="https://www.python.org/dev/peps/pep-0008/#imports">recommendations about imports&lt;/a>.&lt;/p>
&lt;p>To keep your code both readable and maintainable, here are a few general rules of thumb for how to style your imports:&lt;/p>
&lt;ul>
&lt;li>Keep imports at the top of the file.&lt;/li>
&lt;li>Write imports on separate lines.&lt;/li>
&lt;li>Organize imports into groups: first standard library imports, then third-party imports, and finally local application or library imports.&lt;/li>
&lt;li>Order imports alphabetically within each group.&lt;/li>
&lt;li>Prefer absolute imports over relative imports.&lt;/li>
&lt;li>Avoid wildcard imports like &lt;code>from module import *&lt;/code>.&lt;/li>
&lt;/ul>
&lt;p>&lt;a href="https://pypi.org/project/isort/">&lt;code>isort&lt;/code>&lt;/a> and &lt;a href="https://pypi.org/project/reorder-python-imports/">&lt;code>reorder-python-imports&lt;/code>&lt;/a> are great tools for enforcing a consistent style on your imports.&lt;/p>
&lt;h2 id="resource-imports">Resource Imports&lt;/h2>
&lt;p>Sometimes you’ll have code that depends on data files or other resources. If the resource file is important for your package and you want to distribute your package to other users, then a few challenges will arise:&lt;/p>
&lt;ol>
&lt;li>You won’t have control over the path to the resource since that will depend on your user’s setup as well as on how the package is distributed and installed. You can try to figure out the resource path based on your package’s &lt;code>__file__&lt;/code> or &lt;code>__path__&lt;/code> attributes, but this may not always work as expected.&lt;/li>
&lt;li>Your package may &lt;a href="https://realpython.com/python-import/#run-python-scripts-from-zip-files">reside inside a ZIP file&lt;/a> or an old &lt;a href="https://packaging.python.org/discussions/wheel-vs-egg/">&lt;code>.egg&lt;/code> file&lt;/a>, in which case the resource won’t even be a physical file on the user’s system.&lt;/li>
&lt;/ol>
&lt;p>With the introduction of &lt;strong>&lt;code>importlib.resources&lt;/code>&lt;/strong> into the standard library in &lt;a href="https://realpython.com/python37-new-features/#importing-data-files-with-importlibresources">Python 3.7&lt;/a>, there’s now one standard way of dealing with resource files.&lt;/p>
&lt;h3 id="importlibresources">&lt;code>importlib.resources&lt;/code>&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Gives access to resources within packages&lt;/p>
&lt;ul>
&lt;li>A &lt;strong>resource&lt;/strong> is any file located within an importable package. The file may or may not correspond to a physical file on the file system.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Advantages&lt;/p>
&lt;ul>
&lt;li>More consistent way to deal with the files inside your packages&lt;/li>
&lt;li>Gives you easier access to resource files in other packages&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Requirement when using &lt;code>importlib.resources&lt;/code>:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Your resource files must be available inside a regular package. Namespace packages aren’t supported.&lt;/p>
&lt;p>→ In practice, this means that the file must be in a directory containing an &lt;code>__init__.py&lt;/code> file.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="example">Example&lt;/h4>
&lt;p>Assume you have &lt;a href="https://www.gutenberg.org/ebooks/11">resources&lt;/a> inside a package like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">books/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── __init__.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── alice_in_wonderland.png
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── alice_in_wonderland.txt
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>__init__.py&lt;/code> is just an empty file necessary to designate &lt;code>books&lt;/code> as a regular package.&lt;/p>
&lt;p>You can then use &lt;code>open_text()&lt;/code> and &lt;code>open_binary()&lt;/code> to open text and binary files, respectively:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="nn">importlib&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">resources&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="n">resources&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">open_text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;books&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;alice_in_wonderland.txt&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">fid&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">...&lt;/span> &lt;span class="n">alice&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">fid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">readlines&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="n">resources&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">open_binary&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;books&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;alice_in_wonderland.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">fid&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">...&lt;/span> &lt;span class="n">cover&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">fid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>open_text()&lt;/code> and &lt;code>open_binary()&lt;/code> are equivalent to the built-in &lt;code>open()&lt;/code> with the &lt;code>mode&lt;/code> parameter set to &lt;code>rt&lt;/code> and &lt;code>rb&lt;/code>, respectively.&lt;/p>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-primary-100 dark:bg-primary-900">
&lt;span class="pr-3 pt-1 text-primary-600 dark:text-primary-300">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">&lt;p>&lt;code>importlib.resources&lt;/code> became part of the standard library in Python 3.7. However, on older versions of Python, a &lt;a href="https://importlib-resources.readthedocs.io/">backport is available as &lt;code>importlib_resources&lt;/code>&lt;/a>. This backport is compatible with Python 2.7 as well as Python 3.4 and later versions. To use the backport, install it from &lt;a href="https://pypi.org/project/importlib_resources/">PyPI&lt;/a>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">$ python -m pip install importlib_resources
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>To seamlessly fall back to using the backport on older Python versions, you can import &lt;code>importlib.resources&lt;/code> as follows:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">from&lt;/span> &lt;span class="nn">importlib&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">resources&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="ne">ImportError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">importlib_resources&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">resources&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>See the &lt;a href="https://realpython.com/python-import/#handle-packages-across-python-versions">tips and tricks section&lt;/a> of this tutorial for more information.&lt;/p>
&lt;/span>
&lt;/div>
&lt;h2 id="dynamic-imports">Dynamic imports&lt;/h2>
&lt;h3 id="using-importlib">Using &lt;code>importlib&lt;/code>&lt;/h3>
&lt;p>The whole import machinery is available in the &lt;code>importlib&lt;/code> package, and this allows you to do your imports more dynamically.&lt;/p>
&lt;h2 id="python-import-systems">Python Import Systems&lt;/h2>
&lt;h3 id="import-internals">Import Internals&lt;/h3>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-primary-100 dark:bg-primary-900">
&lt;span class="pr-3 pt-1 text-primary-600 dark:text-primary-300">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">The details of the Python import system are described in the official documentation.&lt;/span>
&lt;/div>
&lt;p>At a high level, three things happen when you import a module (or package). The module is:&lt;/p>
&lt;ol>
&lt;li>Searched for&lt;/li>
&lt;li>Loaded&lt;/li>
&lt;li>Bound to a namespace&lt;/li>
&lt;/ol>
&lt;p>For the usual imports—those done with the &lt;code>import&lt;/code> statement—all three steps happen automatically. When you use &lt;code>importlib&lt;/code>, however, &lt;strong>ONLY the first two steps&lt;/strong> are automatic. You need to bind the module to a variable or namespace yourself.&lt;/p>
&lt;div class="flex px-4 py-3 mb-6 rounded-md bg-primary-100 dark:bg-primary-900">
&lt;span class="pr-3 pt-1 text-primary-600 dark:text-primary-300">
&lt;svg height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">&lt;path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="m11.25 11.25l.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0m-9-3.75h.008v.008H12z"/>&lt;/svg>
&lt;/span>
&lt;span class="dark:text-neutral-300">Even when you import only one attribute from a module, the whole module is loaded and executed. The rest of the contents of the module just aren’t bound to the current namespace.&lt;/span>
&lt;/div>
&lt;p>The module cache plays a very important role in the Python import system. The first place Python looks for modules when doing an import is in &lt;code>sys.modules&lt;/code>. If Python finds a module in the module cache, then it won’t bother searching the import path for the module. If a module is already available, then it isn’t loaded again.&lt;/p>
&lt;h3 id="reloading-modules">Reloading modules&lt;/h3>
&lt;p>Use &lt;strong>&lt;a href="https://docs.python.org/library/importlib.html#importlib.reload">&lt;code>importlib.reload()&lt;/code>&lt;/a>&lt;/strong> to reload a module.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">number&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">number&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">answer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">24&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="c1"># Update number.py in your editor. Now `number.answer` is changed to 42.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="nn">importlib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">importlib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reload&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">number&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">module&lt;/span> &lt;span class="s1">&amp;#39;number&amp;#39;&lt;/span> &lt;span class="kn">from&lt;/span> &lt;span class="s1">&amp;#39;number.py&amp;#39;&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">&amp;gt;&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">number&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">answer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="mi">42&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="import-tips-and-tricks">Import Tips and Tricks&lt;/h2>
&lt;h3 id="handle-packages-across-python-versions">Handle packages across Python versions&lt;/h3>
&lt;p>Sometimes you need to deal with packages that have different names depending on the Python version. As long as the different versions of the package are compatible, you can handle this by renaming the package with &lt;code>as&lt;/code>.&lt;/p>
&lt;p>Example:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">from&lt;/span> &lt;span class="nn">importlib&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">resources&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="ne">ImportError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">importlib_resources&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">resources&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In the rest of the code, you can refer to &lt;code>resources&lt;/code> and not worry about whether you’re using &lt;code>importlib.resources&lt;/code> or &lt;code>importlib_resources&lt;/code>. 👏&lt;/p>
&lt;h3 id="handle-missing-packages-use-an-alternative">Handle missing packages: Use an alternative&lt;/h3>
&lt;p>This case is similar to the one above. Also use &lt;code>try...except&lt;/code> to handle.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># import the desired package&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">except&lt;/span> &lt;span class="ne">ImportError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># import an alternative&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="reference">Reference&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://realpython.com/python-import/">Python import: Advanced Techniques and Tips&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>