From 6cdc17b4731ed76607fa20ca07b58e7cf06de078 Mon Sep 17 00:00:00 2001 From: CodeXplore Date: Wed, 6 Dec 2023 22:07:14 +0800 Subject: [PATCH 01/31] Update dotvenv.md --- basics/dotvenv.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/basics/dotvenv.md b/basics/dotvenv.md index aef373e..1a47edf 100644 --- a/basics/dotvenv.md +++ b/basics/dotvenv.md @@ -2,7 +2,7 @@ - Installation: `pip install python-dotenv==1.0.0` - Config file stores in `.env` file ```shell -HUGGINGFACEHUB_API_TOKEN="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" +HUGGINGFACEHUB_API_TOKEN="" ``` - Load environmental variables ```Python From e63299243504cd4e4d682f25f05b24192a9bcf71 Mon Sep 17 00:00:00 2001 From: CodeXplore Date: Wed, 6 Dec 2023 22:07:52 +0800 Subject: [PATCH 02/31] Update daily_knowledge.md --- daily_knowledge.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daily_knowledge.md b/daily_knowledge.md index 5fe76fc..a38db8c 100644 --- a/daily_knowledge.md +++ b/daily_knowledge.md @@ -352,7 +352,7 @@ Name: b, dtype: object - Config file stores in `.env` file ```shell -HUGGINGFACEHUB_API_TOKEN="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" +HUGGINGFACEHUB_API_TOKEN="" ``` - Load environmental variables From 4c1d6d33ffaf78ac8048804d99c1b71974ea615d Mon Sep 17 00:00:00 2001 From: CodexploreRepo Date: Wed, 20 Dec 2023 16:43:23 +0700 Subject: [PATCH 03/31] update the color map for matplotlib --- daily_knowledge.md | 27 +++++++++++++++++++++++++++ requirements.txt | 3 +++ 2 files changed, 30 insertions(+) diff --git a/daily_knowledge.md b/daily_knowledge.md index 5fe76fc..b9fd305 100644 --- a/daily_knowledge.md +++ b/daily_knowledge.md @@ -4,6 +4,33 @@ - `bytes("yes", "utf-8")` convert string to binary objects: +### Matplotlib + +- Color Map + +```Python +cmap = plt.get_cmap("viridis") +fig = plt.figure(figsize=(8, 6)) +m1 = plt.scatter(X_train, y_train, color=cmap(0.9), s=10) +m2 = plt.scatter(X_test, y_test, color=cmap(0.5), s=10) +``` + +- Plot 2 charts on the same figure with share x-axis + +```Python +fig, ax1 = plt.subplots() + +ax1.hist(housing["housing_median_age"], bins=50) + +ax2 = ax1.twinx() # key: create a twin axis that shares the same x-axis +color = "blue" +ax2.plot(ages, rbf1, color=color, label="gamma = 0.10") +ax2.tick_params(axis='y', labelcolor=color) +ax2.set_ylabel("Age similarity", color=color) # second y-axis's measurement + +plt.show() +``` + ### Relative import ``` diff --git a/requirements.txt b/requirements.txt index 77005ea..ff786b3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,6 @@ attrs black pydantic pyaml +tqdm +librosa +wandb From 0a65f1ef6e79dd09e98ccf19ab43799b07eddae9 Mon Sep 17 00:00:00 2001 From: CodexploreRepo Date: Sat, 13 Jan 2024 17:24:45 +0800 Subject: [PATCH 04/31] update dk for sys module --- daily_knowledge.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/daily_knowledge.md b/daily_knowledge.md index 44e425e..9e11b4d 100644 --- a/daily_knowledge.md +++ b/daily_knowledge.md @@ -1,5 +1,33 @@ # 2023 +## Day 9 + +### `sys` module + +- The kernel knows to execute this script with a **python** interpreter with the shebang `#!/usr/bin/env python` +- `sys.argv[0]` return name of the script +- `sys.argv[1:]` return the arguments parsed to the script + +```Python +############################# +# in the python_script.py # +############################# +#!/usr/bin/env python +import sys +for arg in reversed(sys.argv[1:]): + print(arg) + +############################# +# in the interactive shell # +############################# +bash-5.2$ chmod +x python_script.py +bash-5.2$ ./python_script.py a b c +# Running: ./python_script.py +# c +# b +# a +``` + ## Day 8 - `bytes("yes", "utf-8")` convert string to binary objects: From c90f19a148d895f81e0d5624a820401c919f5a00 Mon Sep 17 00:00:00 2001 From: CodexploreRepo Date: Tue, 6 Feb 2024 18:19:17 +0700 Subject: [PATCH 05/31] update subprocess --- basics/README.md | 4 +- .../google_colab_tutorial.ipynb | 0 basics/notebooks/subprocess.ipynb | 277 ++++++++++++++++++ basics/subprocess_tutorial.py | 1 - daily_knowledge.md | 40 +++ 5 files changed, 319 insertions(+), 3 deletions(-) rename basics/{ => notebooks}/google_colab_tutorial.ipynb (100%) create mode 100644 basics/notebooks/subprocess.ipynb delete mode 100644 basics/subprocess_tutorial.py diff --git a/basics/README.md b/basics/README.md index 93e414d..0bf6f8a 100644 --- a/basics/README.md +++ b/basics/README.md @@ -3,9 +3,9 @@ ## Topics - [`*args` and `**kwargs`](./args_kwargs_tutorial.py) -- [Google Colab](./google_colab_tutorial.ipynb) +- [Google Colab](./notebooks/google_colab_tutorial.ipynb) - [Pathlib](./pathlib_tutorial.py) -- [Subprocess](./subprocess_tutorial.py) +- [Subprocess](./notebooks/subprocess.ipynb) - [YAML](./yaml/README.md) ## Argument Parser diff --git a/basics/google_colab_tutorial.ipynb b/basics/notebooks/google_colab_tutorial.ipynb similarity index 100% rename from basics/google_colab_tutorial.ipynb rename to basics/notebooks/google_colab_tutorial.ipynb diff --git a/basics/notebooks/subprocess.ipynb b/basics/notebooks/subprocess.ipynb new file mode 100644 index 0000000..180151e --- /dev/null +++ b/basics/notebooks/subprocess.ipynb @@ -0,0 +1,277 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Subprocess\n", + "- `subprocess.run` is a higher-level wrapper around Popen that is intended to be more convenient to use.\n", + " - Usage: to run a command and capture its output\n", + "- `subprocess.call` \n", + " - Usage: to run a command and check the return code, but do not need to capture the output.\n", + "- `subprocess.Popen` is a lower-level interface to running subprocesses\n", + " - Usage: if you need more control over the process, such as interacting with its input and output streams." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## subprocess.run()\n", + "- `subprocess.run()` method is a convenient way to run a subprocess and wait for it to complete.\n", + " - Once the subprocess is started, the `run()` method blocks until the subprocess completes and returns a `CompletedProcess` object\n", + "- `subprocess.run()`'s input arguments:\n", + " - `args`: The command to run and its arguments, passed as a **list of strings**.\n", + " - `capture_output`: When set to True, will capture the standard output and standard error.\n", + " - `text`: when set to True, will return the stdout and stderr as string, otherwise as bytes `b'/Users/codexplore/Developer/repos/`.\n", + " - `check`: \n", + " - when check is set to True, the function will check the return code of the command and raise a `CalledProcessError` exception if the return code is non-zero. \n", + " - when check is set to False (default), the function will not check the return code and will not raise an exception, even if the command fails.\n", + " - `timeout`: A value in seconds that specifies how long to wait for the subprocess to complete before timing out.\n", + "- `subprocess.run()`` method also returns a `CompletedProcess` object, which contains the following attributes:\n", + " - `args`: The command and arguments that were run.\n", + " - `returncode`: The return code of the subprocess.\n", + " - `stdout`: The standard output of the subprocess, as a bytes object.\n", + " - `stderr`: The standard error of the subprocess, as a bytes object.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import subprocess" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "total 40\n", + "drwxr-xr-x 4 codexplore staff 128 Feb 6 17:32 \u001b[1m\u001b[36m.\u001b[m\u001b[m\n", + "drwxr-xr-x@ 8 codexplore staff 256 Feb 6 17:32 \u001b[1m\u001b[36m..\u001b[m\u001b[m\n", + "-rw-r--r--@ 1 codexplore staff 18414 Oct 22 10:29 google_colab_tutorial.ipynb\n", + "-rw-r--r-- 1 codexplore staff 0 Feb 6 17:32 subprocess.ipynb\n" + ] + }, + { + "data": { + "text/plain": [ + "CompletedProcess(args=['ls', '-la'], returncode=0)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "subprocess.run([\"ls\", \"-la\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "result = subprocess.run([\"pwd\"], capture_output=True, text=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('/Users/codexplore/Developer/repos/python/basics/notebooks\\n', '')" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.stdout, result.stderr" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.returncode" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## subprocess.call()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.9.6\n", + "Command executed successfully.\n" + ] + } + ], + "source": [ + "return_code = subprocess.call([\"python3\", \"--version\"])\n", + "\n", + "if return_code == 0:\n", + " print(\"Command executed successfully.\")\n", + "else:\n", + " print(\"Command failed with return code\", return_code)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## subprocess.Popen()\n", + "- `Popen` allows you to start a new process and interact with its standard input, output, and error streams. It returns a handle to the running process that can be used to wait for the process to complete, check its return code, or terminate it.\n", + "- The Popen class has several methods that allow you to interact with the process, such as `communicate(`), `poll()`, `wait()`, `terminate()`, and `kill()`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.9.6\n", + "\n" + ] + } + ], + "source": [ + "import subprocess\n", + "\n", + "p = subprocess.Popen([\"python3\", \"--version\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)\n", + "\n", + "output, errors = p.communicate()\n", + "\n", + "print(output)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Subprocess `PIPE`\n", + "- A `PIPE` is a unidirectional communication channel that connects one process's standard output to another's standard input. " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ouptut:\n", + "google_colab_tutorial.ipynb\n", + "subprocess.ipynb\n", + "\n", + "Error : None\n" + ] + } + ], + "source": [ + "# creates a pipe that connects the output of the `ls` command to the input of the `grep` command,\n", + "ls_process = subprocess.Popen([\"ls\"], stdout=subprocess.PIPE, text=True)\n", + "\n", + "grep_process = subprocess.Popen([\"grep\", \".ipynb\"], stdin=ls_process.stdout, stdout=subprocess.PIPE, text=True)\n", + "\n", + "output, error = grep_process.communicate()\n", + "\n", + "print(f\"Ouptut:\\n{output}\")\n", + "print(f\"Error : {error}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "google_colab_tutorial.ipynb\n", + "subprocess.ipynb\n", + "\n" + ] + } + ], + "source": [ + "result = subprocess.run([\"ls\"], stdout=subprocess.PIPE)\n", + "\n", + "print(result.stdout.decode()) # decode() to convert from bytes to strings\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/basics/subprocess_tutorial.py b/basics/subprocess_tutorial.py deleted file mode 100644 index 54d5ee6..0000000 --- a/basics/subprocess_tutorial.py +++ /dev/null @@ -1 +0,0 @@ -# Link: https://www.simplilearn.com/tutorials/python-tutorial/subprocess-in-python \ No newline at end of file diff --git a/daily_knowledge.md b/daily_knowledge.md index 9e11b4d..30492eb 100644 --- a/daily_knowledge.md +++ b/daily_knowledge.md @@ -2,6 +2,46 @@ ## Day 9 +### `subprocess` module + +- `subprocess.run` is a higher-level wrapper around Popen that is intended to be more convenient to use. + - Usage: to run a command and capture its output +- `subprocess.call` + - Usage: to run a command and check the return code, but do not need to capture the output. +- `subprocess.Popen` is a lower-level interface to running subprocesses + + - Usage: if you need more control over the process, such as interacting with its input and output streams. + +- A `PIPE` is a unidirectional communication channel that connects one process's standard output to another's standard input. + +```Python +# creates a pipe that connects the output of the `ls` command to the input of the `grep` command, +ls_process = subprocess.Popen(["ls"], stdout=subprocess.PIPE, text=True) + +grep_process = subprocess.Popen(["grep", ".ipynb"], stdin=ls_process.stdout, stdout=subprocess.PIPE, text=True) + +output, error = grep_process.communicate() + +print(f"Ouptut:\n{output}") +print(f"Error : {error}") + +# Ouptut: +# google_colab_tutorial.ipynb +# subprocess.ipynb +# +# Error : None +result = subprocess.run(["ls"], stdout=subprocess.PIPE) + +print(result.stdout.decode()) # decode() to convert from bytes to strings +# google_colab_tutorial.ipynb +# subprocess.ipynb +``` + +#### `subprocess` vs `os.system` + +- `subprocess.run` is generally more flexible than `os.system` (you can get the stdout, stderr, the "real" status code, better error handling, etc.) +- Even the [documentation for `os.system`](https://docs.python.org/3/library/os.html#os.system) recommends using subprocess instead. + ### `sys` module - The kernel knows to execute this script with a **python** interpreter with the shebang `#!/usr/bin/env python` From 6c249b42ab9f6837dc505516fa678522e882a143 Mon Sep 17 00:00:00 2001 From: CodexploreRepo Date: Thu, 22 Feb 2024 21:45:33 +0800 Subject: [PATCH 06/31] update the typing Annotated, and float decimal conversion --- daily_knowledge.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/daily_knowledge.md b/daily_knowledge.md index 30492eb..97653a0 100644 --- a/daily_knowledge.md +++ b/daily_knowledge.md @@ -1,5 +1,60 @@ # 2023 +## Day 10 + +### Pandas + +#### `.read_csv()` by chunk + +- If the csv file is large, can consider to read by chunk + +```Python +df_iter = pd.read_csv(file_path, iterator=True, chunksize=100000) +df = next(df_iter) +``` + +### Python + +#### typing `Annotated` + +- `Annotated` in python allows developers to declare the type of a reference and provide additional information related to it. + +```Python +from typing_extensions import Annotated +# This tells that "name" is of type "str" and that "name[0]" is a capital letter. +name = Annotated[str, "first letter is capital"] +``` + +- Fast API examples: + ```Python + from fastapi import Query + def read_items(q: Annotated[str, Query(max_length=50)]) + ``` + - The parameter `q` is of type `str` with a maximum length of 50. + +#### Float to Decimal conversion + +- Convert `float` directly to `Decimal` constructor introduces a rounding error. + +```Python +from decimal import Decimal +x = 0.1234 +Decimal(x) +# Decimal('0.12339999999999999580335696691690827719867229461669921875') +``` + +- **Solution**: to convert a float to a string before passing it to the constructor. + - You also can round the float before converting it to string + +```Python +Decimal(str(x)) +# Decimal('0.1234') +Decimal(str(round(x,2))) +# Decimal('0.12') +``` + +- + ## Day 9 ### `subprocess` module From 65c070c92bf4b46dc5648ad266ddf3bb76e12ab2 Mon Sep 17 00:00:00 2001 From: CodexploreRepo Date: Thu, 22 Feb 2024 21:50:16 +0800 Subject: [PATCH 07/31] update lru cache --- assets/img/lru_cache_example.png | Bin 0 -> 53745 bytes daily_knowledge.md | 12 ++++++++++++ 2 files changed, 12 insertions(+) create mode 100644 assets/img/lru_cache_example.png diff --git a/assets/img/lru_cache_example.png b/assets/img/lru_cache_example.png new file mode 100644 index 0000000000000000000000000000000000000000..e09c4e221fd48b4ecd85b93ccdc6a62f0f990b9a GIT binary patch literal 53745 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