58
  1. I am using poetry to create .whl files.
  2. I have an ftp sever runing on a remote host.
  3. I wrote a python script (log_revision.py) which save in a database the git commit, few more parameters and in the end send the the .whl(that poetry created) to the remote server ( each .whl in a different path in the server, the path is save in the db) .

At the moment I run the script manually after each time I run the poetry build commend. I know the pyproject.toml has the [tool.poetry.scripts] but i dont get how can i use it to run a python script.

I tried

[tool.poetry.scripts]
my-script = "my_package_name:log_revision.py

and then poetry run my-script but I allways get an error AttributeError: module 'my_package_namen' has no attribute 'log_revision'

1. can some one please help me understand how to run to wish commend?

as a short term option(with out git and params) i tried to use the poetry publish -r http://192.168.1.xxx/home/whl -u hello -p world but i get the following error

[RuntimeError]                                 
Repository http://192.168.1.xxx/home/whl is not defined  

2. what am i doing wring and how can i fix it?

would appricate any help, thx!

helpper
  • 2,058
  • 4
  • 13
  • 32

4 Answers4

105

At the moment the [tool.poetry.scripts] sections is equivalent to setuptools console_scripts.

So the argument must be a valid module and method name. Let's imagine within your package my_package, you have log_revision.py, which has a method start(). Then you have to write:

[tool.poetry.scripts]
my-script = "my_package.log_revision:start"

Here's a complete example:

You should have this folder structure:

my_package
├── my_package
│   ├── __init__.py
│   └── log_revision.py
└── pyproject.toml

The complete content of a functional pyproject.toml is:

[tool.poetry]
name = "my_package"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]

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

[tool.poetry.scripts]
my-script = "my_package.log_revision:start"

[build-system]
requires = ["poetry_core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

and in my_package/log_revision.py:

def start():
    print("Hello")

After you have run poetry install once you should be able to do this:

$ poetry run my-script  
Hello

You cannot pass something to the start() method directly. Instead you can use command line arguments and parse them, e.g. with python's argparse.

Mike Pennington
  • 41,899
  • 19
  • 136
  • 174
finswimmer
  • 10,896
  • 3
  • 34
  • 44
  • thx for the link, tried it out it is only work for me when setting ```my-script = log_revision:start``` ( could not enter the package name). in addition the ```log_revision.py``` should be in the **same level folder** as the ```pyproject.toml``` – helpper Dec 13 '19 at 16:38
  • 7
    is there a way to send some data to the function ```log_revision:start(arg1, arg2)```? – helpper Dec 13 '19 at 18:32
  • 1
    [helpper](https://stackoverflow.com/users/11306005/helpper) I had a hard time finding an example of how to pass arguments to the function, so I asked this [question/answer](https://stackoverflow.com/a/67476157/3954379) – Lucas May 10 '21 at 18:57
  • 2
    How do you set this up so you can run the command directly like you can with `flask run my_app` with setuptools has `entry_points={"console_scripts": ["superset=superset.cli:superset"]}` – rjurney Aug 20 '21 at 00:49
  • 1
    Poetry 1.1.13 raises `The Poetry configuration is invalid: - Additional properties are not allowed ('scritps' was unexpected)` – Prometheus Sep 30 '22 at 11:42
  • 1
    @Prometheus `scritps` looks like you've made a typo. – daviewales Oct 20 '22 at 02:18
  • How do you get the VSCode Python debugger working with this setup? – Jordan Nelson Oct 24 '22 at 17:54
22

Although the previous answers are correct, they are a bit complicated. The simplest way to run a python script with poetry is as follows:

poetry run python myscript.py

If you are using a dev framework like streamlit you can use

poetry run streamlit run myapp.py

Basically anything you put after poetry run will execute from the poetry virtual environment.

DaveR
  • 1,696
  • 18
  • 24
  • Running a python script puts its folder at the beginning of the sys.path. If your script (or an imported module) imports http and there happens to be a an `http.py` in your folder, you will *NOT* get the python http module... – Capi Etheriel Oct 12 '21 at 03:08
16

For future visitors, I think what OP is asking for (a post build hook?) isn't directly supported. But you might find satisfaction from using a tool I wrote called poethepoet which integrates with poetry to run arbitrary tasks defined in the pyproject.toml in terms of shell commands or by referencing python functions.

For example you could define something like the following in your pyproject.toml

[tool.poe.tasks.log_revision]
script = "my_package.log_revision:main" # where main is the name of the python function in the log_revision module
help   = "Register this revision in the catalog db"

[tool.poe.tasks.build]
cmd  = "poetry build"
help = "Build the project"

[tool.poe.tasks.shipit]
sequence = ["build", "log_revision"]
help     = "Build and deploy"

And then execute and of the tasks with the poe CLI like the following which will run the other two tasks in sequence, thus building your project and running the deployment script in one go!

poe shipit

By default tasks are executed inside the poetry managed virtualenv (like using poetry run) so the python script can use dev dependencies.

If you need to define CLI arguments or load values into a task from a dotenv file (such as credentials) then this is also supported.


Update: poetry plugin support

poethepoet can now support post build hooks when used as a poetry plugin. For example when using poetry >=1.2.0b1 you can configure the following to run your log_revision task automatically after poetry build is run:

[tool.poe.poetry_hooks]
post_build = "log-revision"

[tool.poe.tasks.log-revision]
script = "scripts:log_revision"
Nat
  • 2,689
  • 2
  • 29
  • 35
  • 1
    Excellent! Your tool is great. I experience though a small initialization lag when running a task (I guess due to some internal process sub-spawning). – juanmirocks Jul 07 '23 at 13:55
6

Tinkering with such a problem for a couple of hours and found a solution

I had a task to start the django server via poetry script.

Here are the directories. manage.py is in test folder:

├── pyproject.toml
├── README.rst
├── runserver.py
├── test
│   ├── db.sqlite3
│   ├── manage.py
│   └── test
│       ├── asgi.py
│       ├── __init__.py
│       ├── __pycache__
│       │   ├── __init__.cpython-39.pyc
│       │   ├── settings.cpython-39.pyc
│       │   ├── urls.cpython-39.pyc
│       │   └── wsgi.cpython-39.pyc
│       ├── settings.py
│       ├── urls.py
│       └── wsgi.py
├── tests
│   ├── __init__.py
│   └── test_tmp.py
└── tmp
    └── __init__.py

I had to create a file runserver.py:

 import subprocess                                                               
                                                                                   
  def djtest():                                                                   
      cmd =['python', 'test/manage.py', 'runserver']                                                                 
      subprocess.run(cmd)                                                    

then write the script itself pyproject.toml:

[tool.poetry.scripts]                                                           
dj = "runserver:djtest"  

and still make changes to pyproject.toml:

[tool.poetry.scripts]                                                           
dj = "runserver:djtest"

only then command poetry run dj started working

VirtualScooter
  • 1,792
  • 3
  • 18
  • 28