当前位置:网站首页>PIP batch complete uninstall package

PIP batch complete uninstall package

2022-06-26 04:19:00 Baiyukong

Background

Because there are too many third-party libraries installed in my native environment , So I'm going to uninstall them today , But because there are so many , So it's impossible to do it one by one , So I wrote a little script , This article will record the role and use of this script .

If I write this article well , Can you give me Point a praise , Comment on Collection A dragon (*▽*). If you want one Focus on It's not impossible to .

Please join us at the end of this article vote Oh , If What are the shortcomings , also Please put forward in the comment area , Thank you for .

Problem analysis

To achieve the above functions , We need to solve the following problems :

  1. Get all installed packages
  2. Get the dependencies of each package
  3. Command line interaction , Uninstall the specified package

resolvent

The above three questions can be used subprocess.Popen Package to solve . For convenience , Third question use subprocess.run solve .
There are many articles on the Internet that are right subprocess.Popen and subprocess.run The parameters of , I won't go into more details here .
about subprocess.Popen , In addition to the order to be executed , I only set stdinstdoutstderr Parameters .
about subprocess.run , In addition to the order to be executed , I only set the following parameters :

  • universal_newlines , Set the input / output data type ,True For the string , Otherwise, it is a byte string .
  • capture_output , Set whether to display the command execution results ,True Show , Otherwise it doesn't show .
  • input , This is the key , Enables code to interact with the command line , That is, after the command is specified , Enter the content on the command line to execute . The role in this article is to execute pip uninstall 【 Package name 】 Post input y Make sure .

Code details

Import the required libraries first :resubprocess .
Then package the code that unloads a package into a function , as follows ( The chicken code level of this dish is insufficient , Please also point out the problems ):

def uninstall_completely(name):
    #  Libraries that are required or do not need to be uninstalled , You can set it yourself 
    skips = ['pip', 'urllib3', 'setuptools', 'wheel']
    if name in skips or name.startswith('-'):
        return
        
    print(f'Start to uninstall {
      name}')
    
    #  initialization  Popen, Read command  pip show 【 Package name 】  The results of the implementation of 
    pipe = subprocess.Popen(f'pip show {
      name}', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    
    #  If the package is not installed , The exit 
    if b'WARNING: Package(s) not found: ' in pipe.stderr.read():
        print(f'An error occurred when uninstalling {
      name}: {
      name}  non-existent \n')
        return
        
    #  Regular matching obtains all dependent package names 
    # stdout.read()  The result is a string of bytes , Need to be converted to a string 
    requirements = ''.join(re.findall('Requires: (.*?)\r\n', pipe.stdout.read().decode()))
    print(f"{
      name}'s requirements: {
      requirements}")
    
    #  Close the command line 
    pipe.terminate()
    
    #  Uninstall the specified package 
    try:
        #  Carry out orders  pip uninstall 【 Package name 】
        #  After executing the command, you need to enter whether to uninstall  [y/n], Because you want to uninstall , So specified  input  Parameter is  'y'
        obj = subprocess.run(f'pip uninstall {
      name}', universal_newlines=True, capture_output=True, input='y')
        
        #  If something goes wrong , Then the error reason is output 
        if not obj.stderr == '':
            print(obj.stderr)
            return
        #  Otherwise, the uninstall succeeds 
        else:
            print(f'Uninstall {
      name} successfully.')
            
    #  Prevent the program from stopping due to an error in the middle 
    except Exception as e:
        print(f'An error occurred when uninstalling {
      name}: {
      e}')
    
    #  Output results are separated 
    print('-------------------------------------------')
    
    #  Uninstall all dependent packages of the specified package , Call this function recursively 
    for _ in requirements.split(', '):
        if r == '':
            continue
        uninstall_completely(_)

The calling function code is as follows :

for line in subprocess.Popen('pip list', stdout=subprocess.PIPE).stdout.read().decode().split('\n')[2:]:
    name = line.split(' ')[0]
    if name == '':
        continue
    uninstall_completely(name)

among :

  • pip list You can view all currently installed packages .
  • .decode() Because stdout.read() The result is a string of bytes , You need to convert it to a string .
  • [2:] Remove the useless lines as shown in the following figure
     Insert picture description here
    If only a single package is unloaded , Call function directly .
    If you uninstall some packages , Traverse the list and call the functions separately .

Change BUG

When writing code BUG It's not uncommon , But this time very few . The reason for the error is that the encoding error occurred when reading the execution result .
The specific process is run Call in function Popen.communicate() function , as follows :

with Popen(*popenargs, **kwargs) as process:
    try:
        stdout, stderr = process.communicate(input, timeout=timeout)
    except TimeoutExpired as exc:
        process.kill()

And then call Popen._communicate() function , as follows :

try:
    stdout, stderr = self._communicate(input, endtime, timeout)
except KeyboardInterrupt:
    ...

Call again Popen._readerthread() function , as follows :

self.stdout_thread = threading.Thread(target=self._readerthread, 
                                      args=(self.stdout, self._stdout_buff))

to glance at Popen._readerthread() , as follows :

def _readerthread(self, fh, buffer):
    buffer.append(fh.read())
    fh.close()

This will be from Popen.stdout Read command execution result in .

Look again. Popen.stdout Initialization code , as follows :

self.text_mode = encoding or errors or text or universal_newlines
...
self.stdout = io.open(c2pread, 'rb', bufsize)
if self.text_mode:
    self.stdout = io.TextIOWrapper(self.stdout, encoding=encoding, errors=errors)

At this point it becomes clear , If you specify encodingerrorstextuniversal_newlines Any one or more parameters in , It means that the output is character string , And if there is no designation encoding Parameter words , The default is to use gbk code , If the encoding method is different from that in the environment, an error will be reported .

Then we can modify it Popen Source code , stay subprocess pass the civil examinations 767 That's ok self.text_mode Add the following code to the next line of the definition of :

if self.text_mode and encoding is None:
    encoding = sys.getdefaultencoding()

If you want to convert a byte string to a string and do not specify an encoding format , Use the environment default encoding .




ending

Someone wants to study together python My little friends can Private confidence in me Join the group .

That's what I want to share , because A little knowledge , There will be shortcomings , also Please correct .
If you have any questions, you can also leave a message in the comment area .
 Insert picture description here

原网站

版权声明
本文为[Baiyukong]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206260414095176.html