My Python Development Environment, 2018 Edition
jacobian.org
jacobian.org
Earlier this week I wrote about the pains of setting up a Python development experience without Docker, and then compared it to Docker as well.
If anyone is curious, that's located at https://nickjanetakis.com/blog/setting-up-a-python-developme....
By the way, I would say Docker is anything but slow. I get near instant development feedback on my Flask applications, even when running things through Docker for Windows / WSL.
These are pretty big Flask apps too, which have thousands of lines of code, dozens of packages, tons of assets and require running Celery, Postgres, Redis, etc..
So unless your dependences build on macOS (like in my case), everything goes out the door.
using elpy here with a native install and can use e.g. tramp for remote editing/python sessions in most cases (even across machines), but determining docker mount points to edit in-machine not so much..
I suppose one can simply map a local code directory into a runtime environment, but this also makes e.g. interacting with an in-container interpreter a bit bothersome (not so bad actually, but have to set a separate interpreter path to something like 'docker exec -it ctid python'
would like to track this down I suppose
I've also been following this VS Code issue on adding remote docker support for python https://github.com/Microsoft/vscode-python/issues/79#issueco...
However, if you're a hardcore vim guy then I doubt these IDEs are gonna satiate your current flow.
I commented in the issue a few weeks ago: https://github.com/Microsoft/vscode-python/issues/79#issueco....
Once that's implemented, oh man, development nirvana.
Also, I strongly dislike PyCharm. I am a vim guy by heart, but I am generally not against IDEs. VS Code is okayish. For C++ development, I really loved Visual Studio. But PyCharm just feels wrong, bloated, slow and baroque
Project
Project/venv
Project/src
And then have the whole project as a volume. Then your editor can see the same files as you have in the container.Maybe you can use bind mounts, but I'm not sure how well that works in practice, or with eg a package with a native component.
Docker is great for dependencies like databases and queues. I find it totally unnecessary for developing python.
I was trying to create a new project last month trying to put all of these together. One thing that I was stuck in was putting these together:
- non-single-thread-Flask
- Redis pub-sub, subscribe to listen to a channel
- and websocket (such as socket.io) upon receiving redis sub message, pushing the message to client side.
I found out that this was a non-trivial thing to do, as redis subscribe is a blocking function, and I was not able to push websocket message from redis subscribe callback. I wonder how did they do that, if any?
It was really easy to set up with Docker as it just becomes another container in your Compose file.
Nowadays I would just use Pusher.
I use a default.nix file and a requirements.txt file and then with a single command I'm into a shell and virtual environment with all dependencies and packages installed, that I can easily transfer between machines.
That is unless I want to use PyQt5.
A purely functional package manager, distro, devops. And pretty soon, home directory management. Maintaining servers or doing aggressive changes becomes very easy. There's even a Darwin (macOS) implementation now, so you can manage most of your Mac functionally (with heavy usage of defaults under the hood).
It's still lacking a bit on usability, as some things are not as intuitive as in a simple imperative distribution such as Arch or Alpine. Especially if you need to run some prepackaged software that assumes FHS and binds dynamically to some pre-existing dependencies.
But to me, right now if you are a moderately advanced user I don't see a point in running distros that are stuck in the middle (imperative, complex, lots of defaults). It's either one extreme (simple and imperative, e.g. Arch) or the other (functional, NixOS).
In Python (or basically any other language package manager) you can run arbitrary scripts (post-install etc) and so this doesn't lend itself nicely to a reproducible, functional approach.
Then the result of building a particular package is installed in /nix/store/hash-packagename. And this package links to other packages in the nix store using precise hashes. There is no dynamic linking. So the result is referentially transparent. A particular hash is guaranteed to correspond to the same package version, built in the same way and linked to the same dependencies. Furthermore, installing new package versions or modified versions of a package wont overwrite old ones, as hashes are different.
The same concept applies to a whole system setup, which is identified by a hash computed using all options that configure the system plus all packages available in your environment.
People do though.
It's actually pyqtchart and qscintilla that are the problems. They're not packaged for nix and won't install in a virtualenv with pip. Something to do with hardcoded paths for dependencies I think.
I'm going to have a go at writing a nix files that build them from source, with the help of a NixOS expert, so we'll see how that goes.
On the surface from what I've seen it does all the things right and it is kind of what I expected Docker would before I used it.
This seems within reach finally due to where were are getting with containers and orchestration. A bloated electron app plus kube in a VM maybe? Even that much RAM is still cheaper than my time.
Dropdowns for picking out what runtime, what language, what database, what cache, etc. picking where my code lives, then it boots everything up, solves a local hosts entry + ssl cert and keeps my code synced.
I should be able to huck my macbook in a wood chipper to protect my private keys from terrorists, unbox a new one, install my Jetbrains Toolbox, install this thing, and be back up and running fixing responsive text wrapping "bugs" on my marketing landing pages in minutes.
I should be able to hand my git repo to a potato whose wish to become human was granted by a fairy yesterday owing to their exemplary potato-like behavior and expect they can get the thing booted up and start blowing up my test suite and arguing with me about indentation in minutes.
I should be able to receive news of a cool new framework in a cool new language with a cool new runtime and a cool new database written by angels, etched into crystal tablets discovered in the martian polar ice accompanied with proofs that they are both feature complete and error-free then get going on using these gifts bestowed unto mankind in a brand new repo to write a microservice for filling people's inboxes with unsolicited promotions for male enhancement supplements in minutes.
What would be involved in removing it from my system and moving instead to this set of tools?
Not necessarily looking for s step by step answer, just for general suggestions.
My guess is: find out which python the deep learning tools are using, remove Anaconda, and reinstall the python version needed, using the tools from this post. I’ll need to read up on the tools too. Any pitfalls with this approach?
Anaconda might be nicer if the packages you need are C-based and would need compiling on your platform. Depends on your use-case. For experimentation/playing around, stick with what works for you. But if a project required me to install Anaconda, I wouldn’t take it seriously. And pipenv is pretty easy to use, too. So if you plan on distributing it or open-sourcing it, understanding how most other people manage dependencies ouside of conda is going to be useful.
Many data science environments are pretty much based on Anaconda installations.
(See e.g. these dockers: https://github.com/jupyter/docker-stacks/tree/master/scipy-n...)
I mean, all packages I know DONT require Anaconda. But if you need the whole environment, sometimes Anaconda is the easiest tool too install all dependencies.
For hobbyist stuff that’s fine, and I applaud lowering the entry barrier. My issue would be if I needed Anaconda to deploy the project/dependencies into “prod” in some professional capacity, instead of standard Python build tools. Having said that, I’m not terribly familiar with Anaconda, and it seems to leverage virtualenv under the hood, possibly with pre-compiled packages (like wheels?).
If you want a setup which works on various systems, and uses Python numeric packages, usually it is the most failsafe way to use with various OS. (Unless you want to put everything in docker.)
Unless by "professional" you mean "building", well - then you have a point.
The reason that Anaconda exists is to make it easier for people to have consistency between their dev environment, the build environment, and the prod environment. If you're seriously going to build all of the scientific Python stack from scratch, correctly and optimally, for your prod environment (and then also do the same for every dev environment you need to support), then you have way too much time and probably haven't actually tried doing it over any real period of time.
The problem isn't that it's impossible. The problem is that there are dozens of different ways to almost succeed, and you don't run into the problems until way too late.
I've never tried virtualenvs inside anaconda (what would the use case be? anaconda already provides a virtual environment)
pip is perfectly integrated within anaconda, in my experience; What inconsistencies are you talking about?
I must be missing something, but all these use cases (and more) seem to have been covered by miniconda ages ago.
conda works with perfectly well with pip, and creates virtual environments that are at least (in my experience) as good as virtualenv does.
That said anaconda does have a whole variety of extremely annoying quirks, like packages not being backwards compatible with old versions of conda, or conda going crazy and reinstalling itself, or the way the conda-forge repo has far more packages than the official conda repo. It's very far from perfect. But for data science I think it's basically the standard package manager in Python land.
I hear this often, though I cannot remember ever running into a pip package where this was an issue. Out of curiosity, could someone point me to a pip package and its conda equivalent where this is the case?
And by the way Peter, thank you for the amazing work you do.
http://jakevdp.github.io/blog/2016/08/25/conda-myths-and-mis...
Today, pip et. al. has so dramatically improved, that I hardly see a reason to use anaconda. I am not using deep learning stuff, so I cannot comment on this, but for most scientific python stuff (scikit learn, pandas, numpy, etc.). Pip and pre-built wheels work very well.
On my new job, I was given a Windows laptop that I happen to use now for my development work (because I am too stupid/lazy to properly configure and maintain a separate virtual linux machine). And I started with anaconda, assuming it was less trouble, but quickly ran into trouble. pip worked like a charm [].
[] Ironically pip is installed via the anaconda base installation if I am not mistaken :)
Anaconda integrates pip, it doesn't not compete with it.
I find that Anaconda is the best among the virtual python envs I tried; It does as good or better job of separation and tracking installations as any, AND falls back to pip (with complete integration and tracking) when a package is not in the conda repos.
pip inside conda works better than pip outside in my opinion. I don't understand the general sentiment towards (ana)conda.
When new capabilities are added to conda, like the ability to support noarch python packages, you're going to need to be working with an up-to-date version of conda to use those packages. Just `conda update conda`.
> conda going crazy and reinstalling itself
Conda will pretty aggressively auto-update itself. Going crazy and reinstalling is a new one though. File an issue with details at https://github.com/conda/conda
> the way the conda-forge repo has far more packages than the official conda repo
Conda-forge is community driven and more "upstream" than the Anaconda, Inc.-provided 'defaults' repositories. Think of conda-forge like Fedora, and 'defaults' like CentOS/RHEL.
One thing to be aware of is that Anaconda modifies various Jupyter configs / installs some of its own kernels. So it can be a hassle to get back to system python + plain jupyter.
/usr/local/bin/pip*
/usr/local/bin/pip2*
/usr/local/bin/pip2.7*
/usr/local/bin/pip3*
/usr/local/bin/pip3.5*
/usr/local/bin/pip3.6*Why specifically do you use it instead of virtualenv (+virtualenvwrapper)?
It also, like pew, opens the virtualenv in a new shell instead of activating the current shell. A much saner approach.
The UI is also more user friendly: one entry point for everything, pretty colors and icons, auto-correct of package name, and so on.
Using Pipfiles, instead of requirements, are generally a better experience than requirements.txt since it contains dev and prod dependancies and allow separated dependancy pinning, with file hash.
1. It transparently creates the virtualenv for you
2. The pipfile format handles dependencies and version locking (including hashes of packages), including updates. That means that the versions won't change without your knowledge but upgrading to the latest versions of everything is simply running "pipenv update" to have the virtualenv completely rebuilt (i.e. you'll never forget to add a dependency to a requirements file) and the lock file updated so the next time you push your code the same versions you tested are certain to be used.
3. It'll automatically load the .env file for every command – i.e. your project can have "DJANGO_SETTINGS_MODULE=myproject.site_settings" in that file and you will never need to spend time talking about it in the future.
4. It separates regular and developer dependencies so you don't install as much on servers
5. "pipenv check" will let you know whether any of the versions of any of the packages installed have known security vulnerabilities
6. Pipfile also includes the version of the Python interpreter so e.g. your Python 2 project will seamlessly stay on 2.7 until you upgrade even if your system default python becomes 3.
None of this is something you couldn't do before but it's just easier. Every time a Python point release happens you have to rebuild a virtualenv and now it takes 5 seconds and no thought.
pip install -r requirements-to-freeze.txt --upgrade && pip freeze -l -r requirements-to-freeze.txt > requirements.txt
Pipenv makes this much nicer.https://github.com/jazzband/pip-tools would be what I used before pipenv came to be.
1. `pip-sync`, An easy way to ensure my local environment actually matches my defined requirements. I guess the pipenv version of this would be `pipenv uninstall --all && pipenv install` which isn't quite as elegant, but perhaps good enough.
2. The ability to create more than two requirement sets. For my projects it's often handy to three sets of requirements:
• Normal production requirements end users will need to run the app
• CI requirements needed for testing, but not running the app in production (Selenium, Flake8, etc)
• Local debugging tools (ipython, ipdb)
I could include my local debugging tools in the `--dev` requirements, but then I'm unnecessarily making my CI builds slower by adding requirements for packages that should never actually be referenced in committed code. Alternatively, I could leave them out of my dependencies entirely, but then I have to remember to reinstall them every time I sync my local env to ensure it matches the piplock file.
pip-compile --upgrade
pip-compile --upgrade-package
are also necessary features to quickly track your dependencies (and transitive deps).pipenv uses pip-tools, but they haven't exposed these features as far as I can tell.
$ mkdir myproj
$ cd myproj
$ pipenv --python 3.6 # This creates a virtualenv with Python 3.6 for you project.
$ pipenv install flask # This installs flask in your virtualenv.
$ pipenv run flask # This runs flask in your virtualenv.
$ pipenv run python # This runs a REPL with the interpreter of your venv.
$ pipenv shell # This opens a shell in your venv.
Pipenv replaces requirements.txt with Pipfile and Pipfile.lock. (Similar to what you get from npm or yarn in the JS world, and cargo in Rust)If you use pipenv for a project, you no longer need to care about pip, requirements.txt or virtualenv.
Pipenv/Pipfile is the new standard recommended by Python.org/PyPA:
https://packaging.python.org/tutorials/managing-dependencies...
This is where pipenv delivers. It is a destillation of best practices for virtualenv-configuration.
In your overview, I'd just add an example for a dev installation
pipenv install --dev pytestOne thing that annoys me on VSC is that some operations (jump to defnition etc.) have delays on larger projects, because it does not create an "index db" of your code behind the scenes like PyCharm does, so it can show you usage and search for stuff practically instantly.
Overall VSC is great for developing Python on not-huge and well-behaved projects. For degenerated overgrown messes it's not a good solution :)
The parent comment was about Visual Studio(https://www.visualstudio.com/vs/python/), and you seem to be commenting about Visual Studio Code(http://code.visualstudio.com), which are 2 totally different products.
Microsoft has terrible naming practices.
I never understood the need for virtualenv and similar. Do people really encounter trouble with conflicting packages that often? I try to write scripts so they run on different versions of python anyway, unless there is a very specific reason why that is not possible; and even then you can run python versions in parallel on a Debian/Ubuntu box, with different pip installs for each of them.
As for production, I usually ship things in a Docker container anyway, so there is no chance of mismatched libraries.
I guess I just never saw a problem that virtualenv solves.
My package supports several optional back-ends, selectable at run-time, and it runs under Python 2.7 and 3.6+. I use tox to manage different virtualenvs for the combination of {backend X but not Y or Z, Python 2.7}, {backend X but not Y or Z, Python 3.6}, etc. for Y, and Z, as well as {backend X and Y and Z} for the two versions. Oh, and I support several releases of each of the X, Y, and Z. That's a lot of virtualenvs.
Usually I only develop on the X+Y+Z version because full test suite across all the combinations takes about 15 minutes.
I also do coverage testing, and the Python coverage tool isn't hard to use under this setup to combine tox results across multiple virturalenvs.
I don't know if Docker is better. I've been using this setup for some years.
I install foo 1.0, which depends on frob >= 1.0 (which happens to be frob 1.1 when I installed it). Foo 1.1 comes out, as does frob 1.2 and 1.3. If I reinstall from the pipfile, do I get foo 1.0 with frob 1.3?
I ask because that sounds like a bug waiting to happen. IMO, frozen requirements should remain frozen.
You type `pipenv install foo`. It will create the virtualenv if necessary and adds `foo = " * "` to the packages section of the Pipfile. The Pipfile.lock file will add a section for the package you installed _and_ all of its dependencies, including the hashes of the downloaded packages.
That avoids accidental breakage if the package you depend on doesn't set their versions correctly but it also means that your main Pipfile documents the things which you intentionally installed so a year from now you're not wondering why all of your servers have frob 1.2 installed, which only works on Python 2.7, even though nothing you're using now depends on it.
As a concrete example, here's what `pipenv install requests` looks like in a clean project:
Pipfile:
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[packages]
requests = " * "
[dev-packages]
(had I used `--python $(which python2.7)` it'd have recorded that as well)Pipfile.lock:
{
"_meta": {
"hash": {
"sha256": "a0e63f8a0d1e3df046dc19b3ffbaaedfa151afc12af5a5b960ae7393952f8679"
},
"host-environment-markers": {
"implementation_name": "cpython",
"implementation_version": "3.6.4",
"os_name": "posix",
"platform_machine": "x86_64",
"platform_python_implementation": "CPython",
"platform_release": "17.4.0",
"platform_system": "Darwin",
"platform_version": "Darwin Kernel Version 17.4.0: Sun Dec 17 09:19:54 PST 2017; root:xnu-4570.41.2~1/RELEASE_X86_64",
"python_full_version": "3.6.4",
"python_version": "3.6",
"sys_platform": "darwin"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"name": "pypi",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
},
"default": {
"certifi": {
"hashes": [
"sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296",
"sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d"
],
"version": "==2018.1.18"
},
"chardet": {
"hashes": [
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691",
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"
],
"version": "==3.0.4"
},
"idna": {
"hashes": [
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4",
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f"
],
"version": "==2.6"
},
"requests": {
"hashes": [
"sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
"sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
],
"version": "==2.18.4"
},
"urllib3": {
"hashes": [
"sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b",
"sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f"
],
"version": "==1.22"
}
},
"develop": {}
}
(EDITED: the HN Markdown parser appears to be a simple regex match and breaks formatting with a * and uses only the ASCII definition of whitespace so I couldn't use a zero-width space. The real output doesn't have spaces around the asterisks).Yes it's quite common. For example I work on multiple projects with different versions of Django being used in each one.
That gets messy. What if you want to setup a new machine? Or a new employee's machine? Etc..
It isn't only about conflicting packages.
Installing on another machine is just a matter of pip install -r requirements.txt, if it's for a dev. other wise it's just a docker run ....
I do know that most Python devs use virtualenv, I just never understood what all the fuss is about. Of course I don't mind if the others in team use it, I just never saw the appeal so I'm curious what other peoples' reasons are.
Maybe I don't see the need because I came to Python quite late, a little before Docker came around, and we were early adopters for Docker. So we solved testing and production with Docker (and thus never needed to support multiple Python versions in parallel). It's really one of those small mysteries I don't understand. :)
If that was one environment (forget some of them being stuck on 2.x) the number of damn dependencies would be monstrous!
When I need to bring a partner onto the project, I can't give them a requirements file that's 5x what it should be!
> I just never understood what all the fuss is about.
It's to keep environments clean + easy to maintain. Virtual is probably a bad word for it. It isn't like Docker or a VM.
I don't think too many Python projects that are not libraries support many versions, that isn't the point of virtualenv or conda anyway.
It can also occur as projects age, especially with 3rd party libraries who don't provide API backwards compatibility (which I fully acknowledge is a PITA to develop for, more effort than is frequently justifiable).
Both of these are why I prefer to use the standard library when possible. It's going to remain API stable for a very long time, and the occasional 2-3 lines of boilerplate to do HTTPS requests (and other similar convenience functions) is a cost I'm willing to bear for that stability.
I'll have to respectfully disagree with this one. Everyone pulls in requests the moment they have to make any kind of http request for the sole reason that it's more ergonomic, not because it's "needed".
And requests brings in 4 of its own dependencies. Right there you've created a prime chance for everything to go sideways (and I've watched it happen explicitly with the requests library as it bolts on more and more ergonomic features).
For what it's worth, the last web app I built had a DB library from the OS vendor, flask, and gunicorn. All of which, since they were quite stable, never introduced library conflicts.
I sometimes feel that Docker containers are a bit misused if they are just used as environment capsules. They provide more isolation (process space, etc.). But of course, that would be still fine.
The software I write mostly does not require databases and other supporting services to run on my laptop. So virtualenvs are all I need (most of the time). There is a docker tax that I don't want to pay, unless I heavily benefit from it.
I guess, if I could deploy docker images, the return of invest would be much better and I might use it more.
Just a note of clarification. There are two "visual studio"s:
https://www.visualstudio.com/vs/python/
This is the classic Visual Studio & runs on Windows only, is a full featured IDE and has goodies like mixed mode Python/C++ debugging.
https://code.visualstudio.com/docs/languages/python
This VS Code, a cross-platform Editor++ with Python support.
Both are being actively worked on and will see continuous improvements.
[disclaimer: manage the dev team]
I primarily develop on Fedora which ships both Python 2.7 and Python 3.6.
pip and virtualenv are built into python3, no need to install anything. Additionally, these tools + tox are commonly used for python testing in popular python projects [0]. I have found other colleagues that use other tools struggle with pip and virtualenv, and it puts them at a disadvantage when it comes to working with the larger python software community IMO.
[0] https://github.com/pallets/flask/blob/master/.travis.yml
This is pedantry, and the article is otherwise quite informative, but describing WSL as "Linux-ish" is like describing a speedboat as "car-ish" because they both happen to have steering wheels.
WSL is a bloody marvel of engineering, but it is in no way an equivalent of Linux. I'm mentioning this because WSL proponents and detractors tend to miss the fact that understanding those differences is critical to understanding and using--even in trivial ways--WSL itself.
I'm running linux at work and usually keep it alive for days, so tmux is used for session keeping and remote work. I've created a few bash scripts which run some tmux commands for setting up the layout as I want it and also execute "workon" for the specific virtualenv.
For working on a new project, I've another bash script which I run with the repo url and automatically clones it, creates the virtualenv with the same name as the project, installs dependencies and starts a new tmux sessions with two panes in first window and a second window for other stuff.
The great thing about tmux for me is it's low memory footprint so I can have 10-15 sessions running at a time, without worrying about the computer slowing down. What takes a bit too long is setting it up again upon a restart.
Have you tried this tmux plugin? https://github.com/tmux-plugins/tmux-resurrect I use it all the time at work and at home
> source env/bin/activate
How does one activate one environment over another?Why is pipsi a separate thing?
> pipenv run {command}
This mirrors how npm works.There's also:
> pipenv shell
to give you a shell in which the environment is setup correctly for youIt seems it keeps a ledger somewhere (haven't dug into it). Then to run commands, instead of using `python main.py`, you now use `pipenv run python main.py` and it automates things. It still depends on Virtualenv.
As an alternative, Pyenv + Pyenv Virtualenv work by creating the environments in a separate folder. You can then `cd` into a project root folder and there use `pyenv local x` and every time you `cd` into the directory or a subdirectory, it looks up the tree until it finds a `.local` file. This specifies the environment. It can be a Python version or a Virtualenv and it loads it.
[0] https://github.com/pypa/pipenv/blob/4f2295a1dbf7fe6fa36ef4ec... [1] https://github.com/pypa/pipenv/blob/4f2295a1dbf7fe6fa36ef4ec...
I tried virtualenv wrapper a while ago, and that was basically just another set of commands to do the same thing as virtualenv. Having already learned virtualenv command that gave me no real advantage. Are any of these tools mentioned any different?
I have no clue why a sane person would run npm.
What was that you were implying about how the choice of millions is probably pretty good?
Are you implying that because something is popular, it's therefore "good"?
python3 -m pip install -t .pip ...
export PYTHONPATH=".pip:$PYTHONPATH"
Use whatever directory name you prefer instead of .pip. Mucking with PYTHONPATH is a bit dirty.all I need to work on a client project is basically:
cd /path/to/project
docker-compose build (just once)
docker-compose up
EDIT: "python3 <script.py>" doesn't always work because some scripts are written in bash and they call python within the script.
$ pyenv virtualenv 3.6 some-name
$ echo some-name > /path/to/project/.python-version
$ cd /path/to/project
$ pip install -r requirements.txt
That’s it.My question is now that I'm having to do more PHP development again: is there anything like this for PHP? Last time I looked it seems there were a couple attempts (including phpenv[0]) but that they never caught on or were abandoned.
Is there something like this for PHP? If not, any idea why not? Is phpenv so stable that it hasn't need to be touched in 5 years?
> I need to develop against multiple Python versions, including 2.7, various Python 3 versions (3.5 and 3.6, mostly), and PyPy.
The article states that this is an "unusual" setup, but unfortunately it is all too common. The Python 2/3 split has created such a large and sad schism in the development community, has wasted countless developer hours, and has held back the language itself incalculably. A travesty.
I think Docker is cool in general but for other stuff than this specific use-case.
Virtualenv is literally a set of shims in your $PATH and some tooling to manage those sets. Pyenv is the same thing, but extends the concept out to your actual Python interpreter and lets you rapidly switch between them.
Docker container is just the lazy solution
That said, main reason to do it is that python is a language of idioms and this is one. It's easier to take the trail than break your own.
I can see Docker being slower if virtualized, but on Linux, it’s just a fancier BSD jail, no?
For deployment, Docker solves a lot of problems but there's a significant cost for local development.
This is the important point of Docker. If your app has dependencies that are outside of the Python ecosystem (especially the pita ones to install) Docker seems like an excellent solution. I have an app that requires Oracle drivers and some other binaries with custom compile options (not available through apt) on Linux and I really wish I had built it in Docker.
The process and FS isolation also make sysadmin-me all tingly inside. That way you can't hose up anybody else's clean install either (even if you're compromised).
As a side note, on mac, the VM that runs docker containers requires less ram and CPU than Hipchat. Go figure.
But I understand. If the workflow works for you and/or your team, well, what's the problem? It's working!
Manually installed packages are already segregated and can be uninstalled ya know. Might be a problem if you have no admin skills.
I think you may be the one without admin skills if you think working on your system Python is anything except reckless. No one cares that you have 20 years of doing it like that, it's a poor argument and shows up a really bad attitude.
On the contrary, if it rarely to never happens compared to the effort involved, it's not "reckless" at all, but a tradeoff. The site package folders are a simple path of files/folders, not hard to reason about. Nothing gets "hosed" without your participation. No need to live in mortal fear. In other words the cure is as bad as the disease.
The truth is that venvs are a hack with a lot fewer use cases now that user packages at the low-end and containers at the mid/high-end are now ubiquitous.
Honestly newbies would be a lot better off just avoiding venvs entirely. I make an exception for pipenv when appropriate since it hides the complexity as well as possible.
A native python app in "Docker/Containers" is going to look like a dockerfile that includes a copy of the app and runs three commands. Either you build that on the server (what's the point) or use a registry (additional complexity for little benefit).
It's been working great for me. Pyenv and virtualenvwrapper are really good. I'm not sure why this one needs pipsi, though. You can install CLI tools for both Python 2 and 3 using just Pyenv as demonstrated above.
[0] https://medium.com/@henriquebastos/the-definitive-guide-to-s...
pipenv
pyenv
mkvirtualenv
virtualenv
pipsi
venv
pew
conda
virtualenvwrapper
i'm sure i'm forgetting like 5.
this is like https://xkcd.com/927/
for the record i use pyenv and virtualenv (although playing with ML i'm using conda)
pyvenv (see comment section, edited) is now deprecated and venv is recommended (shipped as part of Python 3.6 installation) is another confusion. Lest not forget the confusion of distuilts and setuptools is like argparse vs optparse in the past (which are both horrible). The experience of using pip and pypi (now Warehouse) is much better than that of Ruby and of NodeJS, but these "2-in-1" tools are just ridiculously "creative".
As always, pro-tip: consider using the following to ensure environment is loaded properly when you are deploying production
/full_path/env/bin/python myapp.py --workers=3
over source /full_path/env/activate && python myapp.py --workers=3
The latter is fine when you are doing local development in your terminals.If you go on #python IRC channel, every year a group of helpers will collectively recommend one of the above and then perhaps a different one the following year, so please do yourself a favor, just stick to pip and virtualenv.
Probably exciting for VS users.
Using the 1st method, I am certain the shell isn't being modified and loaded with stuff I don't need, and the command and arguments are explicit (when I look at top, or when I do strace).
Generally, you can continue to do #2; I use it when I am doing development, like having multiple terminals up and just source into the environment, then run pytest instead of the full path to pytest. But I highly recommend #1 when you are running your code in production (webapp or not). I am not too familiar with conda so I will defer that to the experts).
Isn't it `pyvenv` that is deprecated? `pyvenv` != `pyenv`
Corrected in my post.
⟩ pyenv --version
zsh: correct 'pyenv' to 'pyvenv' [nyae]?
$ ( . /full_path/env/bin/activate && python myapp.py --workers=3 )
This works for anything that you'd like a temporary shell for: $ pwd
/home/me
$ ( cd /tmp; pwd )
/tmp
$ pwd
/home/meVirtualenv creates an application directory. Pip install the required packages into it.
Buildout is much more than a Python package manager. It runs pluggable recipes, where building/installing a Python package is only one of the many available recipes. It was invented at a company where I once worked. It replaced huge piles of complicated Makefiles.
Buildout is obviously less popular than other solutions, but I think it manages complexity quite well and saves me a lot of time compared with other ways I could assemble Python software.
There's pyenv, pip and virtualenv/venv (same thing) and then there's a bunch of tools to make them more implicit or ergonomic (if you like the way these tools work more than the base).
So really there's not a multitude of competing standards, there's 2/3 complementary standards and then people building their own tools atop that, not entirely unlike the multitudes of Jabber or Twitter clients we used to have.
Things were worse before virtualenv rose to prominence.
E.g. pipenv <- pew, pyenv <- virtualenv/venv, so that list could be likened to complaining that Python, C, assembly, and CPU microcode is "too many". Sure, you could argue they are usable independent of each other, but you aren't about to say that there are too many pieces of tech there and we should stop and sending raw electricity to the CPU.
I think that list could legitimately be cut down to pipenv and conda (maybe pipsi, but that's just for installing CLI tools and isn't for development). Everything else is lower-level than what most people will need for app development.
Is that really considered Linux at all? I would not say that Wine is Windows, for example.