I'm working on my Flask project in a virtualenv. Every time I start a new terminal, I have to reinitialize these Flask environment variables:
export FLASK_APP="server.py"
export FLASK_DEBUG="1"
My goal is to not have to type them in manually.
I tried writing a Python script that set them, but couldn't make it work. I tried writing a shell script that set them, but Flask would raise an error that said my Python path was incorrect.
Finally, I tried adding the the env vars to the bottom of the virtualenv's activate script. It worked! The env vars are set and Flask runs as expected.
$ source venv/bin/activate
$ flask run
Is it OK to modify the activate script like this? This is just for development purposes.
Yes, setting environment variables in the virtualenv's activate script is fine for managing your development environment. It's described in Flask's docs. They're only active when the env is activated in the terminal, and you have to remember to add them if you create a new env, but there's nothing wrong with it.
With Flask 1.0, you can use dotenv files instead. Install python-dotenv:
pip install python-dotenv
Add a .flaskenv file:
FLASK_APP=server
And the flask command will automatically set them when running a command:
flask run
The advantage of this over messing with the venv is that you can commit this file so it applies anywhere you work on the code.
Modifying venv/bin/activate file is working for you because the environment variable is getting defined inside the virtual environment. When you're using python3 -m venv venv the environment variables are not present in the new virtual environment. Instead of modifying the activate file, you can instead make a shell script which:
Runs venv/bin/activate
Defines the environment variables
Runs the server
First, I tried writing a Python script that set them, but after research, I realized it was not possible(?).
You could use os.environ to do the same from within, but a shell script is better.
Related
I want to write a first_setup.py script, where users can run it for the first time and the script will do the entire setup automatically, namely it will create a virtual environment, activate it, and install the requirements with pip. Users can then start to use the program without worrying about any dependency issue.
Therefore, I used venv together with subprocess library. My Python version is 3.7.5. With the following command, it creates the virtual environment in the working directory:
env_name = ".venv"
subprocess.run(["python", "-m", "venv", env_name])
However, activation doesn't work. I tried to activate it in various ways, for example:
subprocess.run([f"{venv_name}\\Scripts\\Activate.ps1"], shell=True)
This just opens Activate.ps1 in Windows Text Editor like a .txt file (?). I also thought to add .../Scripts/python.exe to the PATH variable, but it didn't work actually.
Furthermore, when the venv created by the script, VS Code pops up a message saying a venv detected, do you want to use it? If I click on Yes, then it changes my interpreter to venv, which is exactly what I want to do, but automatically with the first_setup.py script.
How can I proceed?
Does this first_setup script need to be Python?
The problem is that the activate script sets environment variables for the shell, which is why it’s usually run with ‘source’.
try using bash file:
python3 -m venv venv
source venv/bin/activate
pip install your_library
When serving a Flask app with gunicorn, I assume I should activate the venv before gunicorn myapp:app, since gunicorn is installed in the venv along with other packages and codes comprising the app. In the scenario of using flask run or python myapp.py to run the app, the venv needs to be activated first (in every tutorial and book I've read), so it seems to me that there's no reason the gunicorn case be different.
Then when it comes to making gunicorn a systemd service unit, as I know no way in this scenario to "activate a venv" as in interactive shell, the closest thing I can think of is to put Environment="PATH=/PathToMyApp:other_default_path_var_contents" and Environment="VIRTUAL_ENV=/PathToMyApp/.venv" in the config, along with ExecStart=/PathToMyApp/.venv/bin/gunicorn myapp:app.
However, I found that almost none of the tutorials I read bothers to add these Environment options as I thought. Are those tutorials just wrong about this, or the environment variables are insignificant regarding gunicorn in a virtual environment? If it's the latter, why is that? What's the difference from flask run and python myapp.py cases?
Looking at the official gunicorn docs, the section on systemd says you should define:
WorkingDirectory=/PathToMyApp
ExecStart=/PathToMyApp/.venv/bin/gunicorn myapp:app
This should be enough without having to set PATH or VIRTUAL_ENV environment variables.
Are those tutorials just wrong about this, or the environment variables are insignificant regarding gunicorn in a virtual environment? If it's the latter, why is that? What's the difference from flask run and python myapp.py cases?
When you run python myapp.py with the virtual env activated at your shell it's actually running the python interpreter which is in the virtual env's bin directory. You can demonstrate this as follows:
This will show your system Python:
/tmp $ which python
/usr/local/bin/python
Activate the venv:
/tmp $ . venv/bin/activate
(venv) /tmp $
This will show the python interpreter in the venv:
(venv) /tmp $ which python
/tmp/venv/bin/python
Furthermore when you cat venv/bin/gunicorn the bang line points to the python interpreter in that venv:
#!/tmp/venv/bin/python3
So when you specify this in your systemd unit file as ExecStart (or execute venv/bin/gunicorn directly without the venv activated) it's actually running that with venv/bin/python3, which in turn makes all the dependencies installed in that venv available to the process.
I am new in PyCharm, I use the 2019 CE version.
I have set an environment variable in venv/bin/activate:
# User defined variables:
export DATABASE="postgresql://postgres:postgres#localhost:5432/postgres"
And I can access it using bash:
$ source venv/bin/activate
(venv) $ echo $DATABASE
postgresql://postgres:postgres#localhost:5432/postgres
And when running my script in this environment, it works as expected:
(venv) $ python3 newproject/settings.py
{'database': 'postgresql://postgres:postgres#localhost:5432/postgres'}
It is also automatically done for PyCharm Terminal that natively activates the environment, but I could not succeed in setting it when I run a script.
Anyway, when I specify a Run Configuration to execute a script that needs to access this environment variable, the environment is not loaded automatically before running the script. I have searched almost everywhere, the logical place should be there:
I have found no option (or documentation) to enable virtualenv before running a script. I even tried to add an external tool to manually activate it before it runs the script. But it is useless since executed environments are disjoint: the script does not run in the same environment that venv.
Looking at the python interpreter it seems it is the correct environment.
I know that I can set Environment Variable in this peculiar setup form, but then variables are no longer available when I run the virtual environment, so it is not a solution to me.
My question is then: How can I setup a Run Configuration that activate my environment and run the script within this environment?
I was working in virtual environment but I removed the virtual environment folder in purpose. But I still can run flask restful application as below, while new empty virtual environment(there are no libraries in site packages but even application works like old virtual environment) is active.
flask run
I thought it should have been failed and complaining like:
no module named flask
, because I removed the old proper virtual environment and installed new one then activated it.
And here is the point, when I try the run the main script as below
python3 app.py
It complains as expected:
no module named flask
It seems that when I run with flask run it is not using virtual environment even virtual environment is active. Because of this reason I can't test my application with other python versions and can't test if requirements are installed and run in new other virtual environments. I couldn't understand this behavior of the flask for any help I appreciate.
Thanks in advance.
You may have Flask globally installed.
pip list | grep flask
You can remove that:
pip uninstall flask
or
Create virtualenv with --no-site-packages option:
virtualenv --no-site-packages venv
source venv/bin/activate
Well I figured out what is going on there.
Flask creates a directory named local in home and moved system's interpreter and dependencies there included by flask application that I wrote.
Then it deploys the application from there when run with flask run. So that means my flask app was not running with virtual environment as we guess.
So in that case I recreated my virtual environment and after installing dependencies I run with python3 app.py. Now it seems that it uses the virtual environment dependencies and interpreter.
complete beginner here. Trying to build a flask web app. Using Windows 8.
Having some problems activating my python virtualenv in Cygwin. I have been using git shell up till now with no problems.
I copied my folder ("app") into my cygwin home directory and it is set up like so:
app - templates
- static
- flask - env - scripts - python
- ...
- hello.py
- ...
I change directory into the app folder, then when I type the command to activate my virtualenv:
$ source flask/env/scripts/activate
The terminal shows:
(env)
so I assume that it is working, until I double check which python:
$ which python
and that returns my original global python install, not the virtual environment. I've checked the installed packages to double check which python environment I am using.
I use the same command in git shell and it activates the right virtualenv. Where am I going wrong / what do I need to change? Please let me know if you need any more information.
I created a new virtual environment using cygwin and when I activated the new env, it switched to that environment fine. Why won't it work for the folder which I copied in?
I created a new virtual environment using cygwin and when I activated the new env, it switched to that environment fine. Why won't it work for the folder which I copied in?
This last sentence is the real problem. The way you try to activate is correct. The problem is that the virtualenv directory must not be moved.
The activate script inside the virtualenv uses absolute paths internally. If you move the directory, the paths will no longer work, and so which python finds the first valid binary on PATH, which is your global binary.
If you need to move the project to a different location, and the virtualenv together with it, then recreate the virtualenv, do not copy it.
The recommended practice is to have a requirements.txt file, and install packages using pip install -r requirements.txt.
That way, recreating a virtualenv is very easy: create an empty virtualenv, and run the pip ... command. There should be nothing else inside the virtualenv that needs moving, only what pip put there, or other python installer scripts, if you used any (and which you would need to re-run, in addition to pip).