I have a dilemma setting up a local development projet structure. Here is my setup:
Python 2.7
Django 1.9
Mac OSX El Capitan 10.11
MySQL 5.7
I made a "Mistake" of setting my project globally instead of in a virtual environment (using 'pip' to install everything in />). After reading this article I still don't get all the steps. Is this correct:
I install global python ( pip, virtualenv in '/>' )
I then go to a location where my projects will reside, like /users/user/documents/projects/project1 and from within 'project1' I use 'virtualenv' to create a virtual environment for this project (this creates a /virtual env/ folder inside /project1/ folder)
activate this virtual environment and pip install django
then from within newly created /virtual env/ folder I startprojectwhich creates another /project1/ folder within /virtual env/ folder
with virtual environment still activated in the current shell session, I proceed with creating my scripts, site and app files
Ad 2. should the virtualenv folder be INSIDE the main "project1" folder or should it encompass it?
Ad 4. Is this correct or can I do it without activating virtual environment first?
My structure currently looks like this (starts from the root: /users/myUser/documents/projects/):
/project1/
/website1/
/static/
/templates/
__init.py__
settings.py
urls.py
views.py
wsgi.py
Common solution is to keep virtual environments and projects in separate folders, e.g. have /users/myUser/.venvs for virtual environments and /users/myUser/documents/projects/ for projects. In other aspects you got it pretty much right yourself. So:
You need to install global Python and virtualenv.
Create directoriy for virtual environments, e.g. run mkdir /users/myUser/.venvs.
Create the virtual environment for your project, virtualenv /users/myUser/.venvs/project1_venv.
Activate the environment for your current shell session /users/myUser/.venvs/project1_venv/bin/activate.
Install django and anything else in this environment pip install django, or better use requirements.txt file to keep track of all project dependencies.
Deactivate the environment, run deactivate.
Now when you'll want to run your project using created virtual environment, in your console window run /users/myUser/.venvs/project1_venv/bin/activate and then python /users/myUser/documents/projects/project1/manage.py runserver. You can activate the venv from any directory, it's activated for current shell window and any python ... run in that window after activation will use this virtual environment. The activation script modifies environment variables in a way, so that the interpreter and libraries from venv are used instead of global ones. (Though there are options to use global ones too.)
It doesn't really matter where you store your virtual environment. Find a project structure that works for you.
I wouldn't put the virtual env inside the project, because you shouldn't check it into version control (although you could use an ignore). Normally, you just need to check in your requirements file, so that you can recreate the environment.
I wouldn't put the project inside the virtual env, because virtual envs are disposable. You might want to destroy the virtual env without destroying the project. Also, you might want to run the same project under different virtual envs e.g. test your code on Django 1.8 and 1.9 before upgrading.
You might find virtualenvwrapper useful. It has some tools that make it easy to create and switch between virtual environments. It stores all of your virtual environments in one place, so you don't have to worry about where to put them.
Is this correct or can I do it without activating virtual environment first?
You should activate the virtual environment and install django before you create / work on your project.
Related
I am aware that there are many questions regarding Django and virtual environments, but I cannot wrap my head around the use of virtual environments with respect to deploying my Django app (locally) via uwsgi/nginx.
My setup includes a virtual environment (with Django and uwsgi), my Django app, nginx and PostgreSQL. The app was created before the virtual environment, and I applied only a single change to manage.py:
#!/Users/snafu/virtualdjango/bin/python3
When I start up the uwsgi located in the virtual environment (with the appropriate .ini file), everything works right away, but I wonder why. I did not need to fiddle around with the $PYTHONPATH, or append the site packages directory to the system path in manage.py, or activate the virtual environment at any point (apart from the initial installation of packages), although the boilerplate comment in manage.py explicitly mentions an inactive virtual environment as a possible reason for an import error.
Activating a virtual environment does nothing but prepend the virtual environment's bin/ to the $PATH thus making python and pip without explicit paths running from the virtual environment. Everything else related to virtual environments is implemented inside Python — it automatically changes sys.path and other paths (sys.prefix, sys.exec_prefix, etc).
This means that when you run python with an absolute path from a virtual environment Python automatically activates the virtual environment for this particular Python session. So you don't need to activate the virtual environment explicitly.
There is a minor warning sign on the road though: to run any Python script from a non-activated virtual environment you must set the shebang for all scripts to point to the virtual environment or use sys.executable. Do not use explicit python because that could be a different Python from the $PATH.
To be honest, up until recently I was hoping to avoid everything related to vurtualenvs. Yep, very naïve.
All of the code I write using python is to be deployed using containers, where "one container - one app" is totally true for now. And also number of CLIs being distributed also to my coworkers as wheels.
What I came up with is two "global" environments living in my homedir:
"default" virtual env with python 3.10 and some general packages installed. Using this venv I develop current versions of my applications and do my regular job. It is sourced automatically in .bashrc.
Virtual env with python 3.9. This is used to support legacy versions of/not yet updated applications in case if something should be done to them.
And also for some of the projects there are dedicated virtual envs living in a project folder needed only for this particular project, python version there may vary from 3.7 to 3.10.
As a consequence, I have to change current environment by manually sourcing the right activate script several times a day, and this isn't funny.
After some research on the topic, I found things like virtualenvwrapper, Pipenv and Poetry, but none of them seem to meet all my needs: "global" env to use across multiple projects and outside projects (because of CLIs); ability to create env with given python version; easy switch between virtual envs.
Is there any solution for this?
UPD: Some illustrations
Next virtual environments were created inside ~/pyenv/:
$ virtualenv -p /usr/local/bin/python3.9 default3.9
$ virtualenv -p /usr/local/bin/python3.10 default3.10
Next, .bashrc was updated to do source ~/pyenv/default3.10/bin/activate.
Now, for the vast majority of tasks it is enough: everything needed for day-to-day job is installed in default3.10 venv.
In case I need to switch to python3.9 the following is required:
$ deactivate
$ source ~/pyenv/default3.9/bin/activate
And if then I need to work on some project with its own venv, inside project folder I have to do:
$ deactivate
$ source env/bin/activate
Too many manual inputs. At minimal, I'd like to do something like $ workon default3.9 no matter of the current directory I'm in, and it should activate default3.9 venv correctly if no venv is active right now or if any venv if already active.
The same should work inside project folder: $ workon <local_venv_name> to switch to the venv living in current project folder.
And something like venv create <enterpreter path/py version> to create new "global" or "local" (in current folder only) venv, and venv list to get the list of available "global" and "local" environments.
to use the global environment inside the project's local virtual environment.
set
include-system-site-packages = true
in pyvenv.cfg file located in .venv (virtual environment installation directory) directory of each project.
After learning how to code Python I'm starting to learn and figure out how to structure projects and set virtual environments up, but I can't make my mind up on how are packages managed when the virtual environment is activated. To make an example: I want to make a Django project. So, first of all, mkdir the project folder, cd into it and then execute python -m venv [whatever]. cd into Scripts folder and execute 'activate'. Then, pip install Django and pip list and shows Django. At last, I deactivate the virtual environment and make pip list again. Why is Django listed there? Should it?
You might have installed Django both inside and outside the venv (outside being the system python installation). Deactivate the venv and run pip uninstall django then try again.
Okay, finally I understood what was happening and I didn't realize. On one hand, virtual environments are completely independent from the global or system, so what is being installed in one side it shouldn't affect the other. On the other hand, what happened was, that for being inside the Scripts folder, when trying to execute Python commands I was actually executing the scripts with the same name, which are copies to use with the virtual environment and which can be used calling the "activate" script. There was actually no problem, it was me messed up.
Thanks to all contributors for their help.
When we want to do anything with our python virtual environment in terminal/command prompt/shell, we have to activate it by navigating to the scripts folder. But, what does this activation do?
I can access the contents of the virtualenv folder in file explorer without activating it.
At its core, the main purpose of Python virtual environments is to create an isolated environment for Python projects. This means that each project can have its own dependencies, regardless of what dependencies every other project has.
More interesting are the activate scripts in the bin directory. These scripts are used to set up your shell to use the environment’s Python executable and its site-packages by default.
After activating the environment, we’re now getting a different path for the python executable because, in an active environment, the $PATH environment variable is slightly modified.
Should I create a directory in my virtualenv and save the source code for that specific project there?
Thanks in advance
You're not required to have them related in any way. As long as your env is activated, it doesn't matter where it is.
But what's usually easiest is:
Create an empty directory for your project.
Create the virtualenv under that project directory.
Put the source in a src directory under that project directory (or, for really simple projects, just drop it in the project directory).
That way you can check the env settings into version control alongside your code, and if you use an auto-venv tool it'll activate the env every time you cd into the project directory, and so on.
As a side note, if you're just learning this stuff today, you might want to consider learning pipenv instead of using raw virtual environments.
You can save your project anywhere. But you should activate the virtual environment before working on that project.
You can activate the virtual environment using the following command.
source path-to-virtualenvironment/bin/activate
After activating the virtual environment move to your project location.