0

I'm trying to build a website maker in Python, and it works - up until I decided to put sound effects, which requires playsound. After searching StackOverflow for autoinstalling libraries I found my answer and popped it into setup.py. I then ran the code in Windows to check it worked - it did, but then I remembered that macOS and Linux (in my experience) can't use pip, they only use pip3. So I wrote an except into the setup file so whenever ModuleNotFoundError popped up during the pip sequence it would use pip3 instead. However, all I got (in Ubuntu) was this:

bye@DESKTOP-L5UUI0C:/mnt/f/pythonexperements/webmaker$ python3 1.py
 __          __  _         _ _         __  __       _
 \ \......../ / | |.......(_| |.......|  \/  |.....| |..............
 .\ \../\../ _..| |__  ___ _| |_ ___..| \  / |.__ _| |._____ _ __ ..
 ..\ \/  \/ / _ | '_ \/ __| | __/ _ \.| |\/| |/ _` | |/ / _ | '__|..
 ...\  /\  |  __| |_) \__ | | ||  __/.| |..| | (_| |   |  __| |.....
 ....\/..\/.\___|_.__/|___|_|\__\___|.|_|..|_|\__,_|_|\_\___|_|.....
                                                      by ByeMC; v1.0

Installing required libraries, installing "playsound"
Traceback (most recent call last):
  File "1.py", line 13, in <module>
    from playsound import playsound
ModuleNotFoundError: No module named 'playsound'

During handling of the above exception, another exception occurred: # this is exactly what the terminal produced, please don't edit this line

Traceback (most recent call last):
  File "1.py", line 16, in <module>
    import setup
  File "/mnt/f/pythonexperements/webmaker/setup.py", line 3, in <module>
    import pip
ModuleNotFoundError: No module named 'pip'

The main script for the program:

[...]
print(asciiart)

try:
    from playsound import playsound
except ModuleNotFoundError:
    print('Installing required libraries, installing "playsound"')
    import setup
    install('playsound')
    print('Install done')


playsound('notif')
[...]

The code that autoinstalls the libraries:

# Setup files

import pip

depend = ['playsound']

def install(package):
    import importlib
    try:
        importlib.import_module(package)
    except ImportError:
        try:
            import pip
            pip.main(['install', package])
        except ModuleNotFoundError:
            import pip3
            pip3.main(['install', package])
    finally:
        globals()[package] = importlib.import_module(package)


for x in depend:
    install(x)

I would love if you could help me.

ByeMC
  • 15
  • 3
  • 1
    pip3 is not a module. `import pip` throwing ModuleNotFoundError means that pip itself isn't installed. – SuperStormer Apr 05 '21 at 10:04
  • https://stackoverflow.com/a/62555575/11138259 -- `import subprocess, sys; subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])` -- anyway what you are trying to do, seems like a bad idea. There are better ways to solve this. – sinoroc Apr 05 '21 at 10:06
  • You should create a real `setup.py` using setuptools and add `playsound` to `requirements.txt` instead of these hacks. – SuperStormer Apr 05 '21 at 10:10
  • Sorry, it's not clear what exactly your problem is. Does *the third party library* attempt to use `pip`? Does your code do so? In the latter case, *why* does it do so instead of relying on dependencies being present after installing? Is the `pip`/`pip3` executable actually available for the python version you are using? Note that many Linux package managers install the system python without pip - this is a protection measure to avoid breaking system libraries. – MisterMiyagi Apr 06 '21 at 05:23

1 Answers1

0

pip is a command line program. While it is implemented in Python, and so is available from your Python code via import pip, you must not use pip’s internal APIs in this way

  • The pip code assumes that is in sole control of the global state of the program. pip manages things like the logging system configuration, or the values of the standard IO streams, without considering the possibility that user code might be affected.

  • pip’s code is not thread safe. If you were to run pip in a thread, there is no guarantee that either your code or pip’s would work as you expect.

  • pip assumes that once it has finished its work, the process will terminate. It doesn’t need to handle the possibility that other code will continue to run after that point, so (for example) calling pip twice in the same process is likely to have issues.

More on this subject: https://pip.pypa.io/en/latest/user_guide/#using-pip-from-your-program

You could try another approach to install modules, something like this maybe:

import subprocess
import sys
subprocess.check_call([sys.executable, "-m", "pip", "install", "module_name"])
import os
os.system('pip install module_name')

Another approach if pip is unavailable is something more rudimentary, using builtin modules to download the tar.gz:


#python3
import requests

r = requests.get("https://files.pythonhosted.org/packages/4e/0b/cb02268c90e67545a0e3a37ea1ca3d45de3aca43ceb7dbf1712fb5127d5d/Flask-1.1.2.tar.gz",allow_redirects=True)
with open("Flask-1.1.2.tar.gz","wb") as f:
    f.write(r.content)

#python2
import urllib

r = urllib.URLopener()
r.retrieve("https://files.pythonhosted.org/packages/4e/0b/cb02268c90e67545a0e3a37ea1ca3d45de3aca43ceb7dbf1712fb5127d5d/Flask-1.1.2.tar.gz", "Flask-1.1.2.tar.gz")

afterwards just unpack the archive and cd into the directory and install the module python setup.py install --user

dejanualex
  • 3,872
  • 6
  • 22
  • 37
  • 1
    If the pip module cannot be imported, then it can also not be run for the interpreter. A `sys.executable -m pip ...` also has to import pip. – MisterMiyagi Apr 06 '21 at 05:26
  • You're right @MisterMiyagi, on old systems I used `easy_install` but I think now it's deprecated, without `pip` I think the only solution is to download the 'tar.gz` and install the module manually . – dejanualex Apr 06 '21 at 11:59