Search code examples
pythonpipvirtualenvwindows-subsystem-for-linuxvirtual-environment

Virtualenv on WSL creates different files than Virtualenv on PowerShell


I have WSL installed on my system with Python 3.7.3 running while Python on my main system runs 3.7.4. Both systems have pip (or pip3) installed along with virtualenv 16.x.x and up. My problem is that using virtualenv env on WSL creates a different folder structure than the one on PowerShell but the problem isn't about the different paths, it's about the files that are created in the lib folder.

I have tried reinstalling virtualenv on WSL by doing pip3 uninstall virtualenv however the problem still persists.

https://i.sstatic.net/lplqz.jpg Here are pictures of both WSL and PowerShell.

As you can see, the files created by WSL are 0-1KB in size and is not recognized by Windows as opposed to files created by PowerShell which are fully functioning.

Can someone please explain to me why this happens? Thank you.


Solution

  • Creating a virtualenv in Windows Subsystem for Linux will create a virtualenv that is meant to run on Linux, not on Windows. This is why the files created by virtualenv on WSL are not recognized by Windows (and the files created by virtualenv on Powershell will not be usable in WSL).

    As for why the files are so much larger in the Windows virtualenv, it's because more of them are compiled binary and library files rather than scripts.

    I have two virtualenvs on my dual boot machine, so we can look at them for an equivalent comparison. (one is Python 3.6 and one is Python3.7, but that's not too important.)

    Here are the files for the Windows virtualenv:

       2315 activate*
       1067 activate.bat*
       1755 activate.ps1*
       1517 ativate_this.py*
       1159 activate.xsh*
        603 deactivate.bat*
     102783 easy_install-3.7.exe*
     102783 easy_install.exe*
     103281 f2py.exe*
     102765 pip3.7.exe*
     102765 pip3.exe*
     102765 pip.exe*
    3748368 python37.dll*
      58896 python3.dll*
      99856 python.exe*
      98320 pythonw.exe*
     102761 wheel.exe*
    

    And here are the files for the Linux virtualenv:

       2219 activate
       1438 activate.csh
       3103 activate.fish
       1751 activate.ps1
       1517 activate_this.py
       1160 activate.xsh
        259 easy_install*
        259 easy_install-3.6*
        242 f2py*
        242 f2py3*
        242 f2py3.6*
        150 get_env_details*
        246 pip*
        246 pip3*
        246 pip3.6*
         72 postactivate
         74 postdeactivate
         69 preactivate*
         75 predeactivate
          7 python -> python3*
    4526456 python3*
          7 python3.6 -> python3*
       2348 python-config*
        237 wheel*
    

    As you noticed, the files are a lot smaller for the Linux virtualenv than for the Windows one. This is normal, and not a problem.

    The reason is that more of the file in the Linux virtualenvs are scripts, rather than binaries. Scripts are files with code that will be run by an interpreter, whereas binary files are compiled code that will either be run directly (like .exe files) or be used as a library (like .dll files).

    On the Windows virtualenv, activate, activate.bat, activate.ps1. activate_this.py, activate.xsh, and deactivate.bat are scripts. You can see that their size ranges from 0.6 to 2.3 kB, which is rather small. easy_install-3.7.exe, easy_install.exe, f2py.exe, pip3.7.exe, pip3.exe, pip.exe, python.exe, pythonw.exe, and wheel.exe, on the other hand, are all binary executable files. You can see they range from 98 to 103 kB, which is much larger than the scripts. python37.dll and python3.dll are library files, which are also compiled binary files, but not directly executable, and they are also quite large. python3.dll is much smaller than python37.dll, so python3.dll probably just references python37.dll, but even so, python3.dll is still very large compared to the scripts.

    On the Linux virtualenv, on the other hand, all of the files are scripts except for python, python3, and python3.6. python3 is a binary executable file, and python and python3.6 are just symlinks to python3.

    The reason scripts are typically smaller is because they run code that is actually in the interpreter without incuding that code in the file itself. As an example, let's look at pip.

    Here are the contents of the file pip on the Linux virtualenv:

    #!/home/nog642/.virtualenvs/virtualenv-name/bin/python3
    # -*- coding: utf-8 -*-
    import re
    import sys
    
    from pip._internal.main import main
    
    if __name__ == '__main__':
        sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
        sys.exit(main())
    

    This is a python script, which runs in the virtualenv's python interpreter. It imports the pip module, which is contained elsewhere in the virtualenv's structure, and then runs the main method after doing some parsing on the command-line arguments.

    The actual code for pip is somewhere else, and the actual executable being run is python3, which then runs this script in the interpreter. This is why the file ends up being only 246 bytes.

    pip.exe in the Windows virtualenv, on the other hand, is 102,765 bytes. This is because it is itself an executable binary, and not a script. It contains all the code it needs to run, which has been compiled. Since it is self-contained, and doesn't rely on code elsewhere in the file sctructure, it ends up being larger.