Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Whitespace in root path of virtualenv breaks scripts #53

Closed
vbabiy opened this issue Mar 14, 2011 · 59 comments
Closed

Whitespace in root path of virtualenv breaks scripts #53

vbabiy opened this issue Mar 14, 2011 · 59 comments
Labels

Comments

@vbabiy
Copy link

vbabiy commented Mar 14, 2011

I'm not really sure if this is a distribute/setuptools/virtualenv but,

If I install virtualenv in

/var/lib/hudson/home/jobs/Minification WebHelpers/workspace/python/2.4

then run ./bin/easy_install:

bash: ./bin/easy_install: "/var/lib/hudson/home/jobs/Minification: bad interpreter: No such file or directory

Seems like something does not obey whitespace in path names correctly.


@rguldener
Copy link

+1, confirmed with Mac OS X 10.7.3 and Python 2.7.1

Kind of annoying, would be great to have a fix

@chaoflow
Copy link

We are able to create a virtualenv with spaces in the name (see #278), but easy_install and pip stumble over it later:

% virtualenv "foo bar"
New python executable in foo bar/bin/python
Installing setuptools............done.
Installing pip...............done.
% ./foo\ bar/bin/easy_install nose
zsh: ./foo bar/bin/easy_install: bad interpreter: "/tmp/cfl/foo: no such file or directory
127 % ./foo\ bar/bin/pip install nose 
zsh: ./foo bar/bin/pip: bad interpreter: "/tmp/cfl/foo: no such file or directory

@mattvh
Copy link

mattvh commented Mar 18, 2013

I'm also here to confirm that this is an issue with OS X (10.8 here). If you edit the VIRTUAL_ENV variable and shebangs in bin you can get it to work, but a fresh env chokes on any spaces in a path. Which is a big problem for OS X, given that the boot drive is typically named "Macintosh HD," so every path starts with "/Volumes/Macintosh HD..."

The hack I'm using works as follows.

bin/activate:

VIRTUAL_ENV='/Volumes/Macintosh\ HD/path/to/my/project'

bin/pip and bin/easy_install:

#!"/Volumes/Macintosh\ HD/path/to/my/project/venv/bin/python"

Pip seems to be working after escaping the space in the path.

@zakdances
Copy link

Why was this closed? It's still very much an issue. edit my mistake, it's still open

@qwcode
Copy link

qwcode commented Aug 25, 2013

this issue still shows open.

@1mentat
Copy link

1mentat commented Aug 29, 2013

I was able to get around this my creating a symbolic link from my home directory to the one I was wanting to work in (that otherwise had a space in it).

@michealbeatty
Copy link

I'm seeing this too because Mac. I get around this by manually editing the shebang line in the scripts to !#/usr/bin/env python and all works. However, as others have mentioned, this has to be done with each new env and any additional scripts installed in the env.
Seems this should be an easy fix in the code to either escape the space or use /usr/bin/env if is_darwin. However since I'm pretty much a noob at this I could be wrong.

@Ivoz
Copy link

Ivoz commented Feb 4, 2014

This isn't just for mac, it's basically part of the specification/behaviour of *nix systems.

You can't have spaces in the first argument of the shebang line (they will get turned into separate arguments instead), and normally there's no escaping / quoting allowed either.

http://lists.gnu.org/archive/html/bug-bash/2008-05/msg00053.html

@michealbeatty
Copy link

I know, I ran into this problem with anaconda as well. t's just endemic with Mac because the drive name has the whitespace in it.

@jashephe
Copy link

It looks like this would be corrected by #611. Has there been any review of the efficacy of that pull request?

@diimdeep
Copy link

So annoying, should be fixed asap.

@pfmoore
Copy link
Member

pfmoore commented Feb 24, 2015

See the link @Ivoz posted, this is a Unix limitation. #611 might work for some Unix variants, if they support backslash escapes in a shebang line, but it's not clear which versions do (and the code just blindly does it without checking - which admittedly won't make the problem worse, but won't help either if it's not supported...)

@jashephe
Copy link

It's indeed true that this is a result of the way that unix handles shebang lines, but if #611 fixes the problem for some systems and doesn't worsen the problem for others, would that still be an improvement?

@pfmoore
Copy link
Member

pfmoore commented Feb 24, 2015

If that's true then yes. But I can'rt comment on #611 as I'm not a Unix developer. There might be cases where it makes things worse, I just don't know. Sorry I can't be more help.

@jashephe
Copy link

Fair enough. #611 probably needs to be more carefully looked at and tested for fringe cases.

@acidjunk
Copy link

acidjunk commented Aug 6, 2015

Even worse: on windows it breaks on the default Jenkins path with the same error:
FATAL: whitespaces are not allowed in Python interpreter's path: C:\Program Files (x86)\Jenkins\shiningpanda\jobs\c3418983\virtualenvs\d41d8cd9

davidbstein added a commit to davidbstein/virtualenv_decompressed_scripts that referenced this issue Oct 18, 2015
Fixes issue pypa/virtualenv#53 in bash and shell by using the printf %q "shell quote" formatter, which escapes as appropriate for a given environment. Falls back to quoting some characters that universally need to be escaped. Fallback is needed because there are several printf implementations, not all of which are guaranteed to have the %q formatter (though bash always should).
davidbstein added a commit to davidbstein/virtualenv that referenced this issue Oct 18, 2015
Fixes issue pypa#53 in bash and shell by using the printf %q "shell quote" formatter, which escapes as appropriate for a given environment. Falls back to quoting some characters that universally need to be escaped. Fallback is needed because there are several printf implementations, not all of which are guaranteed to have the %q formatter (though bash always should).

uncompressed diff here: davidbstein/virtualenv_decompressed_scripts@0bc6629
@fbidu
Copy link

fbidu commented Oct 8, 2016

I was just affected by this issue. Following the instructions I found on StackOverflow, I managed to make pip work by just setting the first line to #!/usr/bin/env python

I'm not sure, however, if that solution works for all cases... I mean, I'm not sure about which Python will be executed

@merwok
Copy link

merwok commented Oct 11, 2016

Changing the shebang of installed scripts to “env python” means that they will work only in an activated virtualenv. The scripts were generated with explicit absolute paths so that they would always use the Python in the venv, and thus find the installed packages needed by the scripts.

@pfmoore
Copy link
Member

pfmoore commented Oct 11, 2016

My suggestion would be that someone (probably someone affected by this issue, but at a minimum someone on a platform that has the problem and also has a way of solving it) provide a pull request implementing a check along the lines of:

  • If we have spaces in the pathname,
  • and we are on platform XXX,
  • then write the shebang line with the following escaping to handle the spaces.
  • In all other cases, fall back to the current behaviour.

Further additions could then be made by interested parties just adding extra platform checks.

Ideally, it would be nice to include a comment with a link to the documentation that confirms how platform XXX supports paths with spaces, so that future maintainers have a reference to check against. Personally, I'm not clear what fixes work and where:

  1. the discussion here suggests that double quotes work on OSX, but does that depend on the precise OSX version?
  2. In Fixed file paths with spaces causing pip to choke on *nix systems #611 escaping spaces with backslashes was used, but there was no confirmation as to what OS it was for (Linux? A specific kernel version? A specific distro?)

Note that no such platform-specific variants should use /usr/bin/env. As @merwok pointed out, that results in a change in behaviour - the shebang is deliberately written to allow running the script without activating the environment.

Adding some tests to be sure the behaviour is as expected (including the principle that it falls back when we're not on a specifically recognised platform) would be extremely useful, too, but it would also be fiddly, as it would involve monkeypatching to allow testing for platform XXX when you're not actually running on that platform.

@fbidu
Copy link

fbidu commented Oct 14, 2016

@pfmoore As I mentioned, I was recently affected by this issue and I'm running Linux Mint 18. I have never contributed with Virtualenv but I am currently at Python Brasil and we'll have a day dedicated to sprints, I might give it a try!

@JDLH
Copy link

JDLH commented May 17, 2017

The first virtualenv bug is that virtualenv chose to implement shell-executable files by using a certain Unix kernel feature, despite that feature having limitations that routinely cause problems for virtualenv user. Virtualenv could fix this by using a different mechanism for shell-executable files. The second virtualenv bug is to have no documentation of how users should use virtualenv in order to work around the first bug (create a virtualenv only on short paths with ASCII-only characters and no whitespace). The third virtualenv bug is that it has no mechanism which detects cases where the user chooses a virtualenv path which will trigger the first bug, and print a helpful warning message. There's plenty that virtualenv contributers could do to improve the situation.

@yan12125
Copy link

@JDLH About your first "bug": it's not handled by virtualenv but distlib, and there's an implementation at https://bitbucket.org/pypa/distlib/pull-requests/31/. I hope I could have time to study the internals of distlib and reply to Vinay Sajip's comments properly but unfortunately I don't.

@vsajip
Copy link

vsajip commented May 17, 2017

The first virtualenv bug is that virtualenv chose to implement shell-executable files by using a certain Unix kernel feature

@JDLH This is not specific to virtualenv - all Unix script files (i.e. files with shebang lines) use this kernel feature - and there is no compelling reason for virtualenv (or anything else) to reinvent a completely new method of dispatching scripts, when the existing mechanism is so widely used and well understood. If you wrote a script by hand which had spaces in the interpreter path (no virtualenv involved) it would exhibit the same problem.

There's plenty that virtualenv contributers could do to improve the situation.

There are probably many calls on contributors' time. This issue affects the relatively small number of cases where long paths/paths with spaces are used. Perhaps some of those users who are affected could help the contributors to help them by proposing a patch which would help with the detection and warning messages? Just an idea.

@yan12125 distlib allows one to specify the executable in the shebang line however one wants. The kernel limitation on whitespace / long lines perhaps won't ever be fixed by Linux developers because of backward compatibility. One could just provide a custom string for the shebang executable (incorporating a generalised equivalent to the Mozilla script hack) and distlib should write it into the script, so one can experiment with it just as a distlib user (hence with no need to look at the internals, AFAICT).

@JDLH
Copy link

JDLH commented May 17, 2017

This is not specific to virtualenv

@vsajip This is a true statement — other software uses the same shebang mechanism which virtualenv chose — but it misses the point of this issue. There is nothing about the value provided by virtualenv that demands it use the shebang. virtualenv could use a different mechanism, but it chose the shebang, and thus virtualenv really does inherit the shebang's limitation.

there is no compelling reason for virtualenv (or anything else) to reinvent a completely new method of dispatching scripts

I think what you are saying is that the problems experienced by the people who have encountered this issue over the years are not "compelling". I think the reason why so many people find and comment on this issue over the years is that they do find the problems "compelling". I certainly do.

Perhaps some of those users who are affected could help the contributors to help them by proposing a patch which would help with the detection and warning messages? Just an idea.

I chose the word "contributors" to include both the stalwarts who do most of the work on virtualenv, and the visitors like me who find this problem compelling enough to work on a reducing its impact. It's fair to say that we who find the problem compelling should contribute a patch.

It would be helpful if the stalwarts who know virtualenv well could suggest promising approaches. If I wanted to insert a warning message for the user who types virtualenv ~/my\ long\ path\ with\ spaces, where should that code best reside? Are there non-obvious constraints on such a patch, which the stalwarts could share, to remove an obstacle from the visitor working on their first contribution? Do the stalwarts have some historical objection to accepting such a patch? (I mean, I can't be the first person who thought of adding a warning message. There has to be a reason it hasn't happened yet.)

@revolter
Copy link

revolter commented May 17, 2017

There is one well-known path that contains spaces and cannot be modified: /Users/iulian/Library/Mobile Documents/com~apple~CloudDocs. So anyone who wants to keep some scripts managed with virtualenv in iCloud bumps into this problem.

@pfmoore
Copy link
Member

pfmoore commented May 17, 2017

It would be helpful if the stalwarts who know virtualenv well could suggest promising approaches.

Well, if we knew any, we would probably not have left this issue unresolved for so long, given the amount of criticism we seem to get for doing so :-(

If I wanted to insert a warning message for the user who types virtualenv ~/my\ long\ path\ with\ spaces, where should that code best reside?

You could start by looking at the argument parsing code, adding a check once the path has been determined.

Are there non-obvious constraints on such a patch, which the stalwarts could share, to remove an obstacle from the visitor working on their first contribution?

They can mostly be found by searching the issue list here for the various comments made on this and other issues over the years, but to start with, you need to not reject paths when they will work - and that means working out what limitations the OS imposes. These vary drastically between systems. Windows allows spaces and long filenames, some Unix systems allow spaces, some need paths with spaces to be quoted, some have very short length limits (32 characters?) some longer, ... Many limitations aren't well documented, and very few contributors have access to sufficient systems to be able to test all the possibilities enough to supplement the available docs.

Do the stalwarts have some historical objection to accepting such a patch?

No, other than "don't assume it's as simple as you think at first glance, and don't ignore all of the various (sometimes pretty obscure) systems we have to support".

If someone does want to take a stab at this - and they should be aware that it's not something that I'd personally recommend as a "first contribution" - then they should start by reading all of the history available in the various issues (some linked from this one, others probably not, some probably on the pip tracker and maybe even the distlib or setuptools trackers) and summarise in a new PR the constraints imposed by various OSes. Propose that as a documentation patch that states "unless these conditions are met, the shebang headers used by virtualenv will not work as expected, and so virtualenv does not support creating environments in directories that don't match the stated conditions". The PR can include a code change to warn if the documented conditions are not met, or can propose this as future work (as from what I recall, it's pretty hard to introspect the system details precisely enough to know what limits apply - consider "Ubuntu with a patched kernel"...). Personally, I'd be OK with a warning that only flagged known cases where things would fail, and was silent if it wasn't sure. But I'd also be fine with a docs-only patch at this stage.

You'd then need to get reviews of your patch from people with access to the systems you cover - as noted, the core devs can't really help here because none of us use (for example) FreeBSD, or OpenBSD, or Solaris, or ...

You could also just do a partial job, and create a PR that added docs and a warning only for (say) OSX. I don't know if that would stop the complaints about this issue (I don't have a feel for what systems this comes up on most frequently) but maybe it would be sufficient. Possibly one of the core devs who uses OSX would be OK with merging that.

Does that help?

@raxod502
Copy link

raxod502 commented May 18, 2017

Perhaps I don't understand something, but couldn't this issue be solved by having (for example) bin/pip contain

#!/bin/sh
"/my/long path/with spaces/pythonx.y" "/path/to/my project/with spaces/venv/bin/real-pip" "$@"

and then moving the current pip script to real-pip? I don't see why we have to use the shebang directly.

@pfmoore
Copy link
Member

pfmoore commented May 18, 2017

@raxod502 I assume you're aware this wouldn't work on Windows. Also, I think the "normal" incantation needed on the second line is more complex than the one you give (although I don't know why, personally). You can probably find the proper approach via a web search. With your approach, what would happen for paths with " or $ characters in them?

Assuming you can address these sorts of issue, I guess the next step would be for you to submit a PR (as per the comments above) and we can debate specifics on that. You'd need to get at least one of the virtualenv core committers who works on Unix involved - as a Windows user I wouldn't be willing to merge a Unix-specific PR like this myself.

@gst
Copy link

gst commented May 24, 2017

@pfmoore
proposed solution by @raxod502 could also work on windows with a .bat script file, afaik ?

@pfmoore
Copy link
Member

pfmoore commented May 24, 2017

@gst Short answer, no. Long answer is at http://paul-moores-notes.readthedocs.io/en/latest/wrappers.html There have been many discussions on this point over the years, and every time someone has come up with a solution other than an exe wrapper, it's had problems.

In this case, please remember this problem does not exist on Windows. So there's absolutely no reason to change anything in the Windows environment - any change must be restricted to Unix only.

@gst
Copy link

gst commented May 25, 2017

thx for good answer :)

other than an exe wrapper, it's had problems.

personally I can live with that (if I had to).

@vsajip
Copy link

vsajip commented May 28, 2017

I've updated distlib to handle long paths and paths with spaces. I didn't use Harald Nordgren's patch directly (it had some problems - e.g. no tests) but the approach is the same - using '/bin/sh' as the executable. pip / virtualenv maintainers might want to test after locally vendoring the current version of the distlib repository.

@pradyunsg
Copy link
Member

The development version of pip now does vendor this newer version of distlib, which means pip now handles spaces in directory names just fine.

As I understand it, once the next release of pip and a virtualenv release are made, this issue will get fixed -- any new virtualenv created will support spaces in path, as will binaries installed by pip (except possibly in some quirky cases like setuptools' wrappers that are not directly installed by pip).

@smurf0
Copy link

smurf0 commented Dec 8, 2017

I've just started using gvfs to mount samba shares in user space and find virtualenv/pip etc scuppered on account of punction in the mount paths generated by gvfs.

There are no spaces in the paths, but plenty of other things to bring virtualenv/pip etc to their knees trying to run in a dir like

/run/user/1000/gvfs/smb-share:server=bolt,share=eng/projects/msp/mrfbus/land

As far as I can see there is no option currently in gvfs to prevent punctuation in the paths of it's generated mount points. My only workaround is to never create a virtualenv on a gvfs mount , which seems a little sad

@raxod502
Copy link

raxod502 commented Dec 8, 2017

@pradyunsg Is there any timeline for the next pip release? The last one was over a year ago, and it seems kinda dumb to wait so long for this really simple fix to show up in virtualenv.

@pradyunsg
Copy link
Member

Hi @raxod502!

Yeah, we want to get it out soon. The thing is we're short on developer time to get PEP 518 out the door, which is something we want to do. It might just happen that there's a pip 10 without PEP 518 but again, it depends on finding the time to get the plan settled on that.

@JDLH
Copy link

JDLH commented Oct 14, 2018

It appears this bug is fixed by pip 10.0.0, released 2018-04-14. Strictly speaking the fix was in distlib 0.2.6, which was vendored into pip with their PR4819 in Oct 2017, which first appeared in pip 10.0.0b2.

The underlying fix appears to be in distlib's commit 9285cca. As vsajip commented here on May 28, 2017, the approach follows Harald Nordgren's idea: keep using a simple shebang for simple cases (OS is not Posix, or path is short enough and has no spaces), but for the non-simple cases use a /bin/sh exec command instead, which can handle the long or space-containing paths.

I did a quick test on Mac OS X 10.11.6, making a virtual env in a long path with spaces in it, then invoking pip3 install, and it seems to work. I haven't fully tested that everything described in this bug is fixed on every OS.

@gandie
Copy link

gandie commented Oct 18, 2018

After upgrading pip from 9.0.1 to 18.1 (they switched to calendar based version) and virtualenv from 15.0.1 to 16.0.0 using Ubuntu 16.04.5 LTS the problem seems to be gone:

sudo pip install --upgrade pip
sudo pip install --upgrade virtualenv

Now all pip commands work properly in virtualenvs having spaces in their root path.

@pradyunsg
Copy link
Member

As confirmed by @JLDH and @gandie, this issue has now been resolved; with the latest versions of pip and virtualenv together working properly when the root of a virtualenv has spaces in it.

Closing this! Thanks for the work on the underlying fix @vsajip!

@rirl
Copy link

rirl commented Mar 8, 2019

Old ticket: but why not
#!/usr/bin/env python ?

@JDLH
Copy link

JDLH commented Mar 9, 2019

@rirl , I think leaving a comment on a closed Issue is unlikely to get your idea attention. The problem was given a solution. If you think that the new virtulenv, with this solution, would be improved by doing things differently, then you are proposing a new change. Consider opening a new Issue, say what change you think should happen, and make a case for why the change would be better than the new virtualenv.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests