From b8515e0315d9cea4f77f404091d2a24f5053e29a Mon Sep 17 00:00:00 2001 From: Aleksandra Nenadic Date: Tue, 21 Nov 2023 11:24:40 +0000 Subject: [PATCH 1/2] Switch to python3 -m to install pip --- _episodes/12-virtual-environments.md | 53 +++++++++---------- _episodes/13-ides.md | 21 ++++---- _episodes/16-verifying-code-style-linters.md | 4 +- .../21-automatically-testing-software.md | 31 ++++++----- _episodes/22-scaling-up-unit-testing.md | 4 +- ...ontinuous-integration-automated-testing.md | 4 +- _episodes/43-software-release.md | 4 +- _extras/common-issues.md | 4 +- _extras/databases.md | 2 +- _extras/vscode.md | 2 +- 10 files changed, 62 insertions(+), 67 deletions(-) diff --git a/_episodes/12-virtual-environments.md b/_episodes/12-virtual-environments.md index 9e1eb3a12..9cf882b11 100644 --- a/_episodes/12-virtual-environments.md +++ b/_episodes/12-virtual-environments.md @@ -17,8 +17,8 @@ keypoints: - "Use `pip` to install and manage Python external (third-party) libraries." - "`pip` allows you to declare all dependencies for a project in a separate file (by convention called `requirements.txt`) which can be shared with collaborators/users and used to replicate a virtual environment." -- "Use `pip3 freeze > requirements.txt` to take snapshot of your project's dependencies." -- "Use `pip3 install -r requirements.txt` to replicate someone else's virtual environment on your machine from +- "Use `python3 -m pip freeze > requirements.txt` to take snapshot of your project's dependencies." +- "Use `python3 -m pip install -r requirements.txt` to replicate someone else's virtual environment on your machine from the `requirements.txt` file." --- @@ -220,7 +220,7 @@ conventionally within your software project so they are co-located. This will create the target directory for the virtual environment (and any parent directories that don’t exist already). -> ## What is `-m` Flag in `python3` Command?? +> ## What is `-m` Flag in `python3` Command? > The Python `-m` flag means "module" and tells the Python interpreter to treat what follows `-m` > as the name of a module and not as a single, executable program with the same name. Some modules > (such as `venv` or `pip`) have main entry points and the `-m` flag can be used to invoke them @@ -378,50 +378,45 @@ To install the latest version of a package with `pip` you use pip's `install` command and specify the package’s name, e.g.: ~~~ -(venv) $ pip3 install numpy -(venv) $ pip3 install matplotlib +(venv) $ python3 -m pip install numpy +(venv) $ python3 -m pip install matplotlib ~~~ {: .language-bash} or like this to install multiple packages at once for short: ~~~ -(venv) $ pip3 install numpy matplotlib +(venv) $ python3 -m pip install numpy matplotlib ~~~ {: .language-bash} -> ## How About `python3 -m pip install`? -> Why are we not using `pip` as an argument to `python3` command, -> in the same way we did with `venv` -> (i.e. `python3 -m venv`)? -> `python3 -m pip install` should be used according to the -> [official Pip documentation](https://pip.pypa.io/en/stable/user_guide/#running-pip); -> other official documentation still seems to have a mixture of usages. -> Core Python developer Brett Cannon offers a +> ## How About `pip3 install ` Command? +> You may have seen or used the `pip3 install ` command in the past, which is shorter +> and perhaps more intuitive than `python3 -m pip install`. However, the +> [official Pip documentation](https://pip.pypa.io/en/stable/user_guide/#running-pip) recommends +> `python3 -m pip install` and core Python developer Brett Cannon offers a > [more detailed explanation](https://snarky.ca/why-you-should-use-python-m-pip/) -> of edge cases when the two options may produce different results -> and recommends `python3 -m pip install`. -> We kept the old-style command (`pip3 install`) -> as it seems more prevalent among developers at the moment - -> but it may be a convention that will soon change and certainly something you should consider. +> of edge cases when the two commands may produce different results and why `python3 -m pip install` +> is recommended. In this material, we will use `python3 -m` whenever we have to invoke a Python +> module from command line. {: .callout} -If you run the `pip3 install` command on a package that is already installed, +If you run the `python3 -m pip install` command on a package that is already installed, `pip` will notice this and do nothing. To install a specific version of a Python package give the package name followed by `==` and the version number, -e.g. `pip3 install numpy==1.21.1`. +e.g. `python3 -m pip install numpy==1.21.1`. To specify a minimum version of a Python package, -you can do `pip3 install numpy>=1.20`. +you can do `python3 -m pip install numpy>=1.20`. -To upgrade a package to the latest version, e.g. `pip3 install --upgrade numpy`. +To upgrade a package to the latest version, e.g. `python3 -m pip install --upgrade numpy`. To display information about a particular installed package do: ~~~ -(venv) $ pip3 show numpy +(venv) $ python3 -m pip show numpy ~~~ {: .language-bash} ~~~ @@ -441,7 +436,7 @@ Required-by: contourpy, matplotlib To list all packages installed with `pip` (in your current virtual environment): ~~~ -(venv) $ pip3 list +(venv) $ python3 -m pip list ~~~ {: .language-bash} ~~~ @@ -463,7 +458,7 @@ six 1.16.0 ~~~ {: .output} -To uninstall a package installed in the virtual environment do: `pip3 uninstall package-name`. +To uninstall a package installed in the virtual environment do: `python3 -m pip uninstall `. You can also supply a list of packages to uninstall at the same time. ### Exporting/Importing Virtual Environments Using `pip` @@ -475,11 +470,11 @@ and everyone can replicate equivalent virtual environments on their machines. `pip` has a handy way of exporting, saving and sharing virtual environments. To export your active environment - -use `pip3 freeze` command to produce a list of packages installed in the virtual environment. +use `python3 -m pip freeze` command to produce a list of packages installed in the virtual environment. A common convention is to put this list in a `requirements.txt` file: ~~~ -(venv) $ pip3 freeze > requirements.txt +(venv) $ python3 -m pip freeze > requirements.txt (venv) $ cat requirements.txt ~~~ {: .language-bash} @@ -510,7 +505,7 @@ They can then replicate your environment and install all the necessary packages from the project root as follows: ~~~ -(venv) $ pip3 install -r requirements.txt +(venv) $ python3 -m pip install -r requirements.txt ~~~ {: .language-bash} diff --git a/_episodes/13-ides.md b/_episodes/13-ides.md index fdeb6ae51..5fb7abcc2 100644 --- a/_episodes/13-ides.md +++ b/_episodes/13-ides.md @@ -183,9 +183,9 @@ Let's see this in action through the following exercise. >> ## Solution >> From the previous episode, >> you may remember that we can get the list of packages in the current virtual environment ->> using the `pip3 list` command: +>> using `pip`: >> ~~~ ->> (venv) $ pip3 list +>> (venv) $ python3 -m pip list >> ~~~ >> {: .language-bash} >> ~~~ @@ -206,11 +206,11 @@ setuptools 67.6.1 six 1.16.0 >> ~~~ >> {: .output} ->> However, `pip3 list` shows all the packages in the virtual environment - +>> However, `python3 -m pip list` shows all the packages in the virtual environment - >> if we want to see only the list of packages that we installed, ->> we can use the `pip3 freeze` command instead: +>> we can use the `python3 -m pip freeze` command instead: >> ~~~ ->> (venv) $ pip3 freeze +>> (venv) $ python3 -m pip freeze >> ~~~ >> {: .language-bash} >> ~~~ @@ -227,13 +227,14 @@ python-dateutil==2.8.2 six==1.16.0 >> ~~~ >> {: .output} ->> We see `pip` in `pip3 list` but not in `pip3 freeze` as we did not install it using `pip`. ->> Remember that we use `pip3 freeze` to update our `requirements.txt` file, +>> We see the `pip` package in `python3 -m pip list` but not in `python3 -m pip freeze` +>> as we did not install it using `pip`. +>> Remember that we use `python3 -m pip freeze` to update our `requirements.txt` file, >> to keep a list of the packages our virtual environment includes. >> Python will not do this automatically; >> we have to manually update the file when our requirements change using: >> ~~~ ->> pip3 freeze > requirements.txt +>> python3 -m pip freeze > requirements.txt >> ~~~ >> {: .language-bash} >> @@ -320,7 +321,7 @@ Let's do this as an exercise. >> Let's verify first that the newly installed library `pytest` is appearing in our virtual environment >> but not in `requirements.txt`. First, let's check the list of installed packages: >> ~~~ ->> (venv) $ pip3 list +>> (venv) $ python3 -m pip list >> ~~~ >> {: .language-bash} >> ~~~ @@ -365,7 +366,7 @@ six==1.16.0 >> {: .output} >> `pytest` is missing from `requirements.txt`. To add it, we need to update the file by repeating the command: >> ~~~ ->> (venv) $ pip3 freeze > requirements.txt +>> (venv) $ python3 -m pip freeze > requirements.txt >> ~~~ >> {: .language-bash} >> `pytest` is now present in `requirements.txt`: diff --git a/_episodes/16-verifying-code-style-linters.md b/_episodes/16-verifying-code-style-linters.md index 1b96cfe24..adf314c8d 100644 --- a/_episodes/16-verifying-code-style-linters.md +++ b/_episodes/16-verifying-code-style-linters.md @@ -34,14 +34,14 @@ $ git switch style-fixes Pylint is just a Python package so we can install it in our virtual environment using: ~~~ -$ pip3 install pylint +$ python3 -m pip install pylint ~~~ {: .language-bash} We should also update our `requirements.txt` with this new addition: ~~~ -$ pip3 freeze > requirements.txt +$ python3 -m pip freeze > requirements.txt ~~~ {: .language-bash} diff --git a/_episodes/21-automatically-testing-software.md b/_episodes/21-automatically-testing-software.md index f3500ec40..be5e68829 100644 --- a/_episodes/21-automatically-testing-software.md +++ b/_episodes/21-automatically-testing-software.md @@ -456,7 +456,7 @@ exit the Python console first (either with `Ctrl-D` or by typing `exit()`), then do: ~~~ -$ pip3 install pytest +$ python3 -m pip install pytest ~~~ {: .language-bash} @@ -470,26 +470,25 @@ our virtual environment will now have the `pytest` package installed for use. Now we can run these tests using `pytest`: ~~~ -$ python -m pytest tests/test_models.py +$ python3 -m pytest tests/test_models.py ~~~ {: .language-bash} -Here, we use `-m` to invoke the `pytest` module, +Here, we use `-m` flag of the `python3` command to invoke the `pytest` module, and specify the `tests/test_models.py` file to run the tests in that file explicitly. -> ## Why Run Pytest Using `python -m` and Not `pytest` ? +> ## Why Run Pytest Using `python3 -m pytest` and Not `pytest`? > -> Another way to run `pytest` is via its own command, -> so we *could* try to use `pytest tests/test_models.py` on the command line instead, -> but this would lead to a `ModuleNotFoundError: No module named 'inflammation'`. -> This is because using the `python -m pytest` method -> adds the current directory to its list of directories to search for modules, -> whilst using `pytest` does not - -> the `inflammation` subdirectory's contents are not 'seen', -> hence the `ModuleNotFoundError`. -> There are ways to get around this with -> [various methods](https://stackoverflow.com/questions/71297697/modulenotfounderror-when-running-a-simple-pytest), -> but we've used `python -m` for simplicity. +> `pytest` is another Python module that can be run via its own command but this is a good example +> why invoking Python modules via `python3 -m` may be better (recall the [explanation of Python interpreter's `-m` flag](../12-virtual-environments/index.html#what-is--m-flag-in-python3-command)). +> Had we used `pytest tests/test_models.py` command directly, +> this would have led to a "ModuleNotFoundError: No module named 'inflammation'" error. This is +> because `pytest` command (unlike `python3 -m pytest`) does not add the current directory to its list of +> directories to search for modules, hence the `inflammation` subdirectory's contents are not being +> 'seen' by `pytest` causing the `ModuleNotFoundError`. There are ways to work around this problem +> but `python3 -m pytest` ensures it does not happen in the first place. +> +> {: .callout} ~~~ @@ -603,7 +602,7 @@ Since we've installed `pytest` to our environment, we should also regenerate our `requirements.txt`: ~~~ -$ pip3 freeze > requirements.txt +$ python3 -m pip freeze > requirements.txt ~~~ {: .language-bash} diff --git a/_episodes/22-scaling-up-unit-testing.md b/_episodes/22-scaling-up-unit-testing.md index 3e406e69d..b8b6df58a 100644 --- a/_episodes/22-scaling-up-unit-testing.md +++ b/_episodes/22-scaling-up-unit-testing.md @@ -147,7 +147,7 @@ to install an additional package `pytest-cov` to our virtual environment, which is used by `pytest` to tell us how many statements in our code are being tested. ~~~ -$ pip3 install pytest-cov +$ python3 -m pip install pytest-cov $ python3 -m pytest --cov=inflammation.models tests/test_models.py ~~~ {: .language-bash} @@ -211,7 +211,7 @@ Again, we should also update our `requirements.txt` file with our latest package which now also includes `pytest-cov`, and commit it: ~~~ -$ pip3 freeze > requirements.txt +$ python3 -m pip freeze > requirements.txt $ cat requirements.txt ~~~ {: .language-bash} diff --git a/_episodes/23-continuous-integration-automated-testing.md b/_episodes/23-continuous-integration-automated-testing.md index 439058936..c4cbd8573 100644 --- a/_episodes/23-continuous-integration-automated-testing.md +++ b/_episodes/23-continuous-integration-automated-testing.md @@ -208,7 +208,7 @@ jobs: - name: Install Python dependencies run: | python3 -m pip install --upgrade pip - pip3 install -r requirements.txt + python3 -m pip install -r requirements.txt - name: Test with PyTest run: | @@ -253,7 +253,7 @@ Each of these steps are: In order to locally install our `inflammation` package it's good practice to upgrade the version of pip that is present first, then we use pip to install our package dependencies. - Once installed, we can use `pip3 install -e .` as before to install our own package. + Once installed, we can use `python3 -m pip install -e .` as before to install our own package. We use `run` here to run theses commands in the CI shell environment - **Test with PyTest:** lastly, we run `python3 -m pytest`, with the same arguments we used manually before diff --git a/_episodes/43-software-release.md b/_episodes/43-software-release.md index f6d2499e3..68bb6154f 100644 --- a/_episodes/43-software-release.md +++ b/_episodes/43-software-release.md @@ -57,7 +57,7 @@ We can install Poetry much like any other Python distributable package, using `p ~~~ $ source venv/bin/activate -$ pip3 install poetry +$ python3 -m pip install poetry ~~~ {: .language-bash} @@ -248,7 +248,7 @@ you don't need to run this command yourself, you've already installed it using `poetry install` above. ~~~ -$ pip3 install dist/inflammation*.whl +$ python3 -m pip install dist/inflammation*.whl ~~~ {: .language-bash} diff --git a/_extras/common-issues.md b/_extras/common-issues.md index 1bc208b5f..2aa1adaf5 100644 --- a/_extras/common-issues.md +++ b/_extras/common-issues.md @@ -173,7 +173,7 @@ In order to get `pip` to use the proxy, you need to add an additional parameter when installing packages with `pip`: ~~~ -$ pip3 install --proxy ` +$ python3 -m pip install --proxy ` ~~~ {: .language-bash} @@ -217,7 +217,7 @@ A workaround is to: - Close PyCharm - Downgrade the version of `pip` used by `venv`, e.g. in a command line terminal type: ~~~ - $ pip3 install pip==20.2.4 + $ python3 -m pip install pip==20.2.4 ~~~ {: .language-bash} - Restart PyCharm diff --git a/_extras/databases.md b/_extras/databases.md index b4bc67a65..829dcdaba 100644 --- a/_extras/databases.md +++ b/_extras/databases.md @@ -75,7 +75,7 @@ which contains an **Object Relational Mapping** (ORM) framework. Our first step is to install SQLAlchemy, then we can create our first **mapping**. ``` -$ pip3 install sqlalchemy +$ python3 -m pip install sqlalchemy ``` {: .language-bash} diff --git a/_extras/vscode.md b/_extras/vscode.md index 6796e7088..5165fdbdb 100644 --- a/_extras/vscode.md +++ b/_extras/vscode.md @@ -147,7 +147,7 @@ since then you will be able to run them from the terminal as well. For example, if you want `pylint` and `black` packages, execute the following from the terminal: ~~~bash -$ pip3 install pylint black +$ python3 -m pip install pylint black ~~~ They will now both be available to run as command line applications, From 3449c4eedb0b7cf992fad7bb8fe1270476fd4e0e Mon Sep 17 00:00:00 2001 From: Douglas Lowe <10961945+douglowe@users.noreply.github.com> Date: Tue, 21 Nov 2023 16:11:30 +0000 Subject: [PATCH 2/2] shortening source code lines for python -m addition --- _episodes/12-virtual-environments.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/_episodes/12-virtual-environments.md b/_episodes/12-virtual-environments.md index 9cf882b11..e21c83a38 100644 --- a/_episodes/12-virtual-environments.md +++ b/_episodes/12-virtual-environments.md @@ -222,14 +222,17 @@ This will create the target directory for the virtual environment > ## What is `-m` Flag in `python3` Command? > The Python `-m` flag means "module" and tells the Python interpreter to treat what follows `-m` -> as the name of a module and not as a single, executable program with the same name. Some modules -> (such as `venv` or `pip`) have main entry points and the `-m` flag can be used to invoke them -> on the command line via the `python` command. The main difference between running such modules as -> standalone programs (e.g. executing "venv" by running the `venv` command directly) -> versus using `python3 -m` command seems to be that with latter you are in full control of -> which Python module will be invoked (the one that came with your environment's Python interpreter vs. -> some other version you may have on your system). This makes it a more reliable way to set things -> up correctly and avoid issues that could prove difficult to trace and debug. +> as the name of a module and not as a single, executable program with the same name. +> Some modules (such as `venv` or `pip`) have main entry points +> and the `-m` flag can be used to invoke them on the command line via the `python` command. +> The main difference between running such modules as standalone programs +> (e.g. executing "venv" by running the `venv` command directly) +> versus using `python3 -m` command seems to be that +> with latter you are in full control of which Python module will be invoked +> (the one that came with your environment's Python interpreter vs. +> some other version you may have on your system). +> This makes it a more reliable way to set things up correctly +> and avoid issues that could prove difficult to trace and debug. {: .callout} For our project let's create a virtual environment called "venv".