[Python] I started Poetry & Impression that I moved from Pipenv to poetry

Motivation

I tried poetry because pipenv installation is quite slow these days. I will summarize what I found after using it all over. Since I am using Pipenv, I can compare it with that. Please refer to Official Doc as it does not describe package-related commands (build, publish ...) or detailed functions.

About Poetry

Poetry is a Python package management tool. Like Pipenv, resolve the dependencies and install / uninstall packages, The poetry.lock file allows other users to install the package with the appropriate version and dependencies. A virtual environment is available and packaging is also possible.

environment

Python uses the one installed by pyenv.

Introduction

$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python

PATH is entered in ~ ./bash_profile and poetry starts up.

$ poetry -V
Poetry version 1.0.2

Poetry settings

In the case of pipenv, environment variables were used to set the .venv folder in the project.

Pipenv


$ export PIPENV_VENV_IN_PROJECT=1
$ pipenv install...

In the case of poetry, set from poetry config. You can check the current settings with the --list option. The default is virtualenvs.in-project = false.

poetry


$ poetry config --list
cache-dir = "/home/user/.cache/pypoetry"
virtualenvs.create = true
virtualenvs.in-project = false
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/user/.cache/pypoetry/virtualenvs

Change the settings.

python


$ poetry config virtualenvs.in-project true
$ poetry config --list
cache-dir = "/home/user/.cache/pypoetry"
virtualenvs.create = true
virtualenvs.in-project = true
virtualenvs.path = "{cache-dir}/virtualenvs"  # /home/user/.cache/pypoetry/virtualenvs

Project start

Model generation

Start the project with poetry new and a template will be generated. The following is as per Official Doc.

$ poetry new my-package
Created package my_package in my-package

Generated stationery


my-package
├── pyproject.toml
├── README.rst
├── my_package
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_my_package.py

The generated pyproject.toml is as follows. It seems that pytest is automatically included in dev-dependencies.

pyproject.toml


[tool.poetry]
name = "my-package"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.7"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

However, it is difficult to use the my_package directory inside my-package. You can change the directory name in the package with the --name option.

---- name option

$ poetry new my-package --name app
Created package app in my-package

Model


my-package
├── pyproject.toml
├── README.rst
├── app
│   └── __init__.py
└── tests
    ├── __init__.py
    └── test_my_package.py

----src option

There seems to be a --src option, but it's more complicated, so don't use it.

$ poetry new --src my-package

Model


├── pyproject.toml
├── README.rst
├── src
│   └── my_package
│       └── __init__.py
└── tests
    ├── __init__.py
    └── test_my_package.py

Generate pyproject.toml

If you don't need a template, you can only create pyproject.toml with poetry init. Interactively determine the contents of pyproject.toml like npm init.

$ poetry init

Package name [{folder_name}]:
Version [0.1.0]:
Description []:
Author [None, n to skip]:  n
License []:
Compatible Python versions [^3.7]:

Would you like to define your main dependencies interactively? (yes/no) [yes] no
Would you like to define your dev dependencies (require-dev) interactively (yes/no) [yes] no
Generated file

[tool.poetry]
name = "new_ais"
version = "0.1.0"
description = ""
authors = ["Your Name <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.7"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

Do you confirm generation? (yes/no) [yes] yes

If you do not enter anything for package name, it will be the folder name there. Enter y / n for Author and dependencies. This will create pyproject.toml in the current directory.

If you use it in the same way as Pipenv, it seems easier to start with init.

install

poetry install, like pipenv install, resolves dependencies and installs the required packages from the pyproject.toml created above.

$ poetry new myapp
$ cd myapp
$ poetry install
reating virtualenv myapp in /home/user/workspace/poetry/myapp/.venv
Updating dependencies
Resolving dependencies... (0.5s)

Writing lock file

Package operations: 11 installs, 0 updates, 0 removals

  - Installing more-itertools (8.1.0)
  - Installing zipp (1.0.0)
  - Installing importlib-metadata (1.4.0)
  - Installing pyparsing (2.4.6)
  - Installing six (1.14.0)
  - Installing attrs (19.3.0)
  - Installing packaging (20.0)
  - Installing pluggy (0.13.1)
  - Installing py (1.8.1)
  - Installing wcwidth (0.1.8)
  - Installing pytest (5.3.2)
  - Installing myapp (0.1.0)

The install will create a poetry.lock file where you can see the dependencies.

---- no-root option

poetry installs myapp by default. To avoid this, install with the --no-root option.

  $ poetry install --no-root

---- no-dev option

If you don't want to install dev-dependencies, the --no-dev option is OK.

  $ poetry install --no-dev

add

Install the package. Note that unlike Pipenv, it is an add. Locking is faster than pipenv.

$ poetry add django==2.2.8

For dev-dependencies, the --dev (-D) option.

$ poetry add flake8 -D

If you use the --dry-run option, you can see what is installed without installing.

$ poetry add django --dry-run
Using version ^3.0.2 for django

Updating dependencies
Resolving dependencies... (0.4s)

Package operations: 4 installs, 0 updates, 0 removals, 13 skipped

  - Skipping more-itertools (8.1.0) Already installed
  - Skipping zipp (1.0.0) Already installed
  - Skipping importlib-metadata (1.4.0) Already installed
  - Skipping pyparsing (2.4.6) Already installed
  - ...

update

When updating the packages installed in the project

$ poetry update

Update individually

$ poetry update requests django

As with add, you can see the contents of the update with the --dry-run option.

$ poetry update --dry-run
Updating dependencies
Resolving dependencies... (0.4s)

No dependencies to install or update

  - Skipping more-itertools (8.1.0) Already installed
  - Skipping zipp (1.0.0) Already installed
  - Skipping importlib-metadata (1.4.0) Already installed
  - Skipping pyparsing (2.4.6) Already installed
  - Skipping six (1.14.0) Already installed
  - Skipping atomicwrites (1.3.0) Not needed for the current environment
  - ...

remove

Delete the installed package.

$ poetry remove flask

Note that packages installed in dev-dependencies require the --dev (-D) option.

$ poetry add flake8 -D

$ poetry remove flake8 # failed
[ValueError]
Package flake8 not found

$ poetry remove flake8 -D # OK

You can also use the --dry-run option with remove.

show

Display a list of available packages. Features like an enhanced version of pip list.

$ poetry show
asgiref            3.2.3  ASGI specs, helper code, and ada...
attrs              19.3.0 Classes Without Boilerplate
django             3.0.2  A high-level Python Web framewor...
entrypoints        0.3    Discover and load entry points f...
flake8             3.7.9  the modular source code checker:...
importlib-metadata 1.4.0  Read metadata from Python packages
mccabe             0.6.1  McCabe checker, plugin for flake8
more-itertools     8.1.0  More routines for operating on i...
packaging          20.0   Core utilities for Python packages
pluggy             0.13.1 plugin and hook calling mechanis...
...

Information about packages can also be displayed.

$ poetry show django
name         : django
version      : 3.0.2
description  : A high-level Python Web framework that
            encourages rapid development and clean, pragmatic
            design.

dependencies
 - asgiref >=3.2,<4.0
 - pytz *
 - sqlparse >=0.2.2

---- tree option

Dependencies can be displayed in a tree structure. A function similar to pipenv graph. Actually, it is easy to see because it is a colored output.

  $ poetry show --tree
  django 3.0.2 A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
  ├── asgiref >=3.2,<4.0
  ├── pytz *
  └── sqlparse >=0.2.2
  flake8 3.7.9 the modular source code checker: pep8, pyflakes and co
  ├── entrypoints >=0.3.0,<0.4.0
  ├── mccabe >=0.6.0,<0.7.0
  ├── pycodestyle >=2.5.0,<2.6.0
  └── pyflakes >=2.1.0,<2.2.0
  ...

---- latest (-l) option

View the latest version.

  $ poetry show --latest
  asgiref            3.2.3  3.2.3  ASGI specs, helper code, a...
  attrs              19.3.0 19.3.0 Classes Without Boilerplate
  django             3.0.2  3.0.2  A high-level Python Web fr...
  entrypoints        0.3    0.3    Discover and load entry po...
  flake8             3.7.9  3.7.9  the modular source code ch...
  importlib-metadata 1.4.0  1.4.0  Read metadata from Python ...

----outdated (-o) option

View of older packages.

  $ poetry show -o
  django 2.2.4 3.0.2 A high-level Python Web framework that e...

lock

Lock the dependency specified in pyproject.toml. (Do not install) poetry.lock is generated.

$ poetry lock

env

Virtual environment related commands. For the [python] part, specify 3.7.4 etc.

$ poetry env info            #Information on the current virtual environment
$ poetry env list            #Virtual environment list
$ poetry env remove <python> #Delete virtual environment
$ poetry env use <python>    #Activate or create a virtual environment

In my environment, when virtualenvs.in-project = true, it was not displayed in list and remove did not work. It's a good idea to delete .venv /.

shell

Launch the shell in the virtual environment. Equivalent to pipenv shell.

$ poetry shell

scripts

You can execute the script by entering the following in pyproject.toml.

pyproject.toml


[tool.poetry.scripts]
start = "script:main"

script.py


def main():
    print("Run script with poetry!")
$ poetry run start
Run script with poetry!

Even if you do not enter the virtual environment, if you execute it from a script, it will be executed in the virtual environment.

Handling of arguments

Looking at poetry's scripts executable code, it seems that you can't pass any arguments.

poetry/console/commands/run.py


    #poetry script executable code
    def run_script(self, script, args):
        if isinstance(script, dict):
            script = script["callable"]

        module, callable_ = script.split(":")

        src_in_sys_path = "sys.path.append('src'); " if self._module.is_in_src() else ""

        cmd = ["python", "-c"]

        cmd += [
            "import sys; "
            "from importlib import import_module; "
            "sys.argv = {!r}; {}"
            "import_module('{}').{}()".format(args, src_in_sys_path, module, callable_) #Run
        ]

        return self.env.execute(*cmd)

With the above script settings, ʻimport_module ('script'). main ()is executed, so there is no part to pass arguments in the first place. I often registeredstart =" python manage.py runserver 0.0.0.0:8000 "` in Pipenv, so I was in trouble.

pyproject.toml


[tool.poetry.scripts]
start = "manage:main"

Then, if you set poetry run start runserver 0.0.0.0:8000, it will work for the time being. .. ..

Impressions

-Good (compared to pipenv) Install, add, remove and lock are faster (important) than Pipenv, and the display on the console is easy to see. Functions equivalent to pip list and pipenv graph are also fairly easy to see.

-Perfect (compared to pipenv) Cooperation with venv. It can be used with the same usability as Pipenv. (I'm worried about the behavior at the time of venv in project) There doesn't seem to be a feature that pyenv install can be done from pipenv, but it's okay because it's not something I use often.

-Bad (compared to pipenv) After all the script part. There were many issues, so I'm waiting for improvement. I feel that there are many options. Just remember.

Based on the above points, it seems that poetry will be used. Speaking of luxury, I should have known if it was dev at the poetry show.

reference

Recommended Posts

[Python] I started Poetry & Impression that I moved from Pipenv to poetry
[Python3] List of sites that I referred to when I started Python
[Python] A memo that I tried to get started with asyncio
Why I moved from Java to Dart
I want to use jar from python
I started python
I want to email from Gmail using Python.
[Python] I want to manage 7DaysToDie from Discord! 1/3
I want to use ceres solver from python
What I did when updating from Python 2.6 to 2.7
[Python] I want to manage 7DaysToDie from Discord! 2/3
I want to make C ++ code from Python code!
The story of moving from Pipenv to Poetry
Changes from Python 3.0 to Python 3.5
Changes from Python 2 to Python 3.0
I started to analyze
Python that I would like to recommend to programming beginners
I tried to get started with blender python script_Part 01
I tried to get started with blender python script_Part 02
I wanted to use the Python library from MATLAB
[Python3] I want to generate harassment names from Japanese!
Python development environment construction 2020 [From Python installation to poetry introduction]
I felt that I ported the Python code to C ++ 98.
Post from Python to Slack
I tried to create API list.csv in Python from swagger.yaml
Cheating from PHP to Python
python Condition extraction from a list that I often forget
I want to start a lot of processes from python
Anaconda updated from 4.2.0 to 4.3.0 (python3.5 updated to python3.6)
Migrate from requirements.txt to pipenv
I tried to make a generator that generates a C # container class from CSV with Python
Switch from python2.7 to python3.6 (centos7)
I want to install a package from requirements.txt with poetry
I want to send a message from Python to LINE Bot
Connect to sqlite from python
I tried changing the python script from 2.7.11 to 3.6.0 on windows10
I made something with python that NOW LOADING moves from left to right on the terminal
I made a garbled generator that encodes favorite sentences from UTF-8 to Shift-JIS (cp932) in Python
Getting Started with Poetry From installation to execution and version control
A story that I was addicted to calling Lambda from AWS Lambda.
I want to use a wildcard that I want to shell with Python remove
8 services that even beginners can learn Python (from beginners to advanced users)
I read "Reinforcement Learning with Python: From Introduction to Practice" Chapter 1
I made a library that adds docstring to a Python stub file.
I read "Reinforcement Learning with Python: From Introduction to Practice" Chapter 2
[python] A note that started to understand the behavior of matplotlib.pyplot
Call Matlab from Python to optimize
Link to get started with python
I tried to touch Python (installation)
Create folders from '01' to '12' with python
Post from python to facebook timeline
[Lambda] [Python] Post to Twitter from Lambda!
How to get started with Python
Connect to utf8mb4 database from python
Python (from first time to execution)
Post images from Python to Tumblr
How to access wikipedia from python
Python to switch from another language
I want to debug with Python
Did not change from Python 2 to 3
Update Python on Mac from 2 to 3