Project root as default working directory
If I understand correctly, each time when I run a python script, PyCharm does:
(1) Adds project roots and sources root to PYTHONPATH.
(2) Set working directory to the script's folder and run the script.
However, if I would want to run a script without PyCharm, from a terminal, it would be much easier to run the script from the project's root; so I don't have to make sure that my project root is in PYTHONPATH each time I want to run that script. I asked some people around and they also recommended to always run files from the project's root.
Therefore, I have following questions (and I am really surprised that I couldn't find a similar discussion on the internet):
(1) What is the reason why developers chose PyCharm to run the script from the script's folder by default?
(2) How do I change default run configuration of the python files in the project, in order to set their working directory to project root? So far I only managed to change the setting of individual files.
(3) Is that a good idea to do so, or is that a bad practice? I guess the answer to this question will follow from the answer to the first question. But it's important, so I write it explicitly.
Please sign in to leave a comment.
Reasons to keep working directory in project root exist and are very strong, especially for running tests.
E.g. if you have pytest based tests folder with tree of subfolders and tests, scenarios to use are:
If you check github for well established python packages, you will always find them running test from project root working directory.
Current PyCharm default directory for tests is really annoying, one has either modify it with every run configuration (as default one is always setting working directory into folder of the test file) or to modify test code to detect it's own position and find relevant data files using special tricks.
Pytest also introduces `conftest.py` file. Using test file deeper in the tree shall pick any fixture defined in it's own and any parent directory up to the working directory. Setting working directory to that of current test file effectively hides all `conftest.py` files in any parent directory.
Alternatively, it'd be nice if it was possible to use $PROJECT_DIR$ variable configuration template.
Running tests from the root of a project is how a python project is conventionally tested by any (CI) Continuous Integration system. And so by convention you would have a tox.ini, conftest.py, etc. on the root of the project - so generally speaking running the tests not from the root of the project is wrong and will not replicate what the CI would do.
I use 'Edit configuration templates...' to configure my pytest and Doctest templates to use the root, and this works fine.
The problems are
(1) I'm developing >30 projects and have to repeat this tedious process for each
(2) I need to teach this tedious process to multiple developers - commonly after they request assistance following a long frustration period of trying to figure out why their tests are are not reproduces locally...
I think an easier configuration method is certainly required
Selecting the root project
Chanansh Actually this worked for me, thanks!
Maoz Maylat To avoid this you can set this as the default option for all new projects via File > New Projects Setup > Run Configuration Templates … and then e.g. set the working diretory for Python (pytest, etc.) to
$PROJECT_DIR$
(see also Path variables).We you now open a new project and run a Python file, the working directory will the the project root.
Of course, you can also set it per project as discussed above.
Looks like, for a pytest project, editing 'Python tests / pytest' does not change the working directory or env of new tests.
Editing "Python tests / Autodetect" does fix the new tests. This confused me for a while so I thought I shoud mention it here.
Being able to set $PROJECT_DIR$ as proposed by M Cyraniak would be a lovely feature. Definitly helpful !
There is no "just use" if I have to repeat it for >30 projects (and teach others to do so)
> (1) Adds project roots and sources root to PYTHONPATH
That is correct indeed.
>(2) Set working directory to the script's folder
This is not entirely true, the working directory can be different in some case, you can change it in the specific Run Configuration settings (Working directory field).
>(1) What is the reason why developers chose PyCharm to run the script from the script's folder by default?
I think in most cases it's better to mimic "cd to folder run python script.py"-like behavior when running the arbitrary project files.
>(2) How do I change default run configuration of the python files in the project
It can be done in Run Configuration templates:
>(3) Is that a good idea to do so, or is that a bad practice?
I never do it myself and I see no specific reasons to set the working directory globally to the project root. Anyway, if you project structure assumes such a workflow I see no reasons to not do it if you want to.
I'm with Jan on reasons to make the root of the project the current working directory. I wouldn't make it the default - far too many new Python-ers incorrectly assume that open("file.txt") means that file.txt is in the same folder as the Python file which, whilst being wrong, changing that default in PyCharm would just cause even more confusion.
That said, I would like to see the option more accessible. Maybe a set working directory to script location check box which is checked by default but we could uncheck? In the unchecked state, the wdir parameter to runfile() would be left unset.
Hello @Kevinsuedmersen!
This might be a known usability problem, please take a look https://youtrack.jetbrains.com/issue/PY-50334 and feel free to vote in order to increase its priority.
Will it help to use a workaround provided in the ticket? Just select pytest explicitly ?
Chanansh When trying that, I get the error “Error:Cannot start process, the working directory '$PROJECT_DIR$' does not exist”. If I leave the Working Directory field blank, I get “Error:Cannot start process, the working directory '' does not exist”.
Thank you for the answer.
About (2) - do you mean in some cases the default behaviour is different? Or just that the configuration can be changed?
What you proposed worked for me. (I think I already tried that before, but maybe I didn't select the project properly).
Both options have pros and cons, so I would just stick to the one which is the most common in the community.
Actually, it seems that this settings changes configuration for all of my projects. Is there a way to change the template for each project independently?
Thanks @Bwoodsend for supporting the idea of having working directory set at the project root.
Regarding the new Python-ers being somehow lost in directories - I remember those feelings very well. It was bothering me (and has generated a lot of unnecessary problems) until I realized, I shall fix the current directory to the project root.
Even after editing the working directory in the run config templates, the working directory of new run configs created from a context menu reverted back to the directory in which the test file resides and not the project root. Am I doing something wrong here, or is that a bug?
Dear Antonia,
Thanks a lot for pointing me to this issue. Selecting pytest as the default test runner did indeed solve my problem.
Instead of hard coding the project root, just use $PROJECT_DIR$
I run Intellij, in my case, editing the `working directory` in pytest didn't work, but editing it inside autodetect works just as expected.
Affirming that having to choose between reasonable behavior for my IDE and my CI is frustrating. Please make this a setting that can be checked in, or search for `pytest.ini` and use that as the root.