python模块操作之自动化-从此不愁移机,断网,版本错误,模块缺失......

作为独霸江湖数年的天下第一大剑客,python已经拥有太多的小弟-子模块了,pypi上有几十万个!
我们使用中,经常使用固定的一些模块,但是进场进行更新电脑,移机,重新安装等各种情况下的非个人意愿操作,这时候重新一个一个进行模块安装,尤其是进行对应模块版本的安装就比较麻烦,比如,断网了,不如新服务器未联网,比如网卡坏了,比如在深山里面和心爱的朋友度假(当然没有网络了),。。。。。。这时候唯一的方法就是进行模块的离线安装!
没错,今天的主题就是离线处理我们的轮子们! 什么,你不知道轮子,汽车总见过吧,对就是这个轮子,python中也叫做脱机模块安装包。

  1. 获取当前环境的模块配置:至少有2中方式可以获得模块信息列表
    pip list >>d:\requirements.txt 或者
    pip freeze >>d:\requirements.txt
    这样,我们得到了当前环境的所有模块列表,以及当前的版本号
    打开文件requirements.txt,主要内容如下所示:
    opcua-client0.8.4
    opcua-widgets
    0.6.1
    opencv-contrib-python4.5.5.64
    opencv-python
    4.5.4.60
    opencv-python-headless4.5.4.60
    openpyxl
    3.0.9
    opt-einsum3.3.0
    outcome
    1.1.0
    packaging21.3
    paddle-bfloat
    0.1.7
    paddlepaddle2.3.1
    pandas
    1.4.1
    `
  2. 下载轮子们(脱机安装包):
    根据requirements文件内容,我们可以进行本地化下载模块。执行命令
    pip download pandas==1.4.1
    将会下载脱机安装包(我们的轮子)到当前目录下。
  3. 进行安装,最好直接切换到轮子所在的目录下,执行指令:
    pip install pandas==1.4.1
    即可进行脱机安装
  4. 问题来了,如果有900个模块,是不是要累死了?累不死的话,至少关节炎肯定跑不掉的。我们该怎样避免自我伤害呢? 我们可以自动化…
  5. 我们使用python来实现自我迭代的自动化,就像是银行收到我们的存款,然后再贷给我们一样的骚操作。
  6. 新建一个程序,就像爱护我们的女票一样,给她一个美好的名字,比如operatePythonModulesAutomation.py,是不是很骚气?有长又大小写的…
  7. 给心目中的女票operatePythonModulesAutomation.py添加漂亮花哨的操作代码,主要分为三部分:主程序,操作部分,自动升级部分,另外的 fi __name__不算在里面,因为这个和女票的包包一样,是必不可少的。
  8. 主程序可以简单进行交互,如下示例,完成参数的输入:
def main():
    '''
    生成requirement.txt文件;
    根据requirement文件下载安装包/轮子到当前目录下;
    并且可以进行自动安装(.whl,.tar.gz,.zip),升级等奥做。
    '''
    print('运行本程序前,需要已经安装python,并且设置好python的path路径。只针对安装包进行操作。')
    print('isDownload=True,根据输入的文件列表,将下载的离线安装包/轮子保存到当前目录下。后续可以手动安装。')
    print('isAutoInstall=True,根据输入的文件列表,将自动从固定的站点("https://pypi.douban.com/simple")安装包/轮子。需要手动执行生成的bat文件')
    print('isUpgrade=True,根据输入的文件列表,将自动从固定站点("https://pypi.douban.com/simple")安装包/轮子的升级包。需要手动执行生成的bat文件')
    print('支持 pip freeze > requirements.txt 或者 pip list >>e:\piplist.txt 输出的模块列表文件格式')
    print('自动生成.bat文件,直接执行该文件即可进行自动安装/下载/升级,也可以使用autoExecuteBat参数进行生成bat后的自动执行')
    print('下面开始输入需要的参数:')
    
    choice,right=getChoice()
    while not right:
        choice,right=getChoice()
        
    infile=r'e:\piplist.txt'
    outfile=r'e:\requirements.bat'
    auto='n' #自动执行生成的bat文件
    if(choice>=0 and choice<=4):
        file=input(r"输入模块列表文件路径和文件名称(default='e:\piplist.txt'):")
        if file=='':
            file=infile
        infile=file
        file=input(r"输入.bat文件的路径和文件名称(default='e:\requirements.bat'):")
        if file=='':
            file=outfile
        outfile=file
        auto=input(r"自动执行生成的bat文件?y/n:")
    elif (choice==5):
        file=input(r"输入需要安装的python模块离线包文件的路径(default='e:\packages'):")
        if file=='':
            file='e:\packages'
        infile=file
    elif (choice>=6 and choice <=7):
        file=input(r"输入需要保存的当前计算机python模块列表文件的路径和文件名称(default='e:\requirements.txt'):")
        if file=='':
            file='e:\requirements.txt'
        outfile=file
    
    if(auto.lower()=='y'):
        isAutoRunBat=True
    else:
        isAutoRunBat=False```

9. 操作部分是核心,进行自动项目的执行,如下:
	

```csharp
def OperateOfflinePythonModules(inputFile='requirements.txt',outputfile="./downloadofflinemodules.bat" \
    ,operate=0,autoExecuteBat=False):
    '''根据选择自动生成python模块的批处理下载/安装/升级程序'''
    global requirementFile,modulesSource
    '''请输入选择的操作:
                 0. 生成手动下载python模块的批处理
                 1. 生成自动下载python模块的批处理
                 2. 生成自动下载python模块的批处理,并进行模块升级
                 3. 生成自动升级python模块的批处理
                 4. 生成手动下载指定版本python模块的批处理
                 5. 自动安装指定路径下的离线包
                 6. 生成本地计算机的pthon离线包文件:pip list >>file
                 7. 生成本地计算机的pthon离线包文件:pip freeze >>file 
                 8. 
    '''
    if operate==0:
        isDownload=True;isAutoInstall=False;isUpgrade=False
    elif operate==1:
        isDownload=False;isAutoInstall=True;isUpgrade=False
    elif operate==2:
        isDownload=False;isAutoInstall=True;isUpgrade=True
    elif operate==3:
        isDownload=False;isAutoInstall=False;isUpgrade=True
    elif operate==4:
        isDownload=True;isAutoInstall=False;isUpgrade=False
    elif operate==5:
        
        return instalModules(inputFile)
    elif (operate>=6 and operate <=7):
        if(operate==6):
            exe=f'pip list >>{outputfile}'
        elif(operate==7):
            exe=f'pip freeze >>{outputfile}'
        ret=os.system(exe)    
        return ret,True
    if inputFile=='':
        inputFile=requirementFile
    if outputfile=='':
        outputfile=outputFile
    lines=[]
    with open(inputFile,'rt',encoding='utf-8') as file:     
        firstline=file.readline()
        if(firstline.find('==')<0): #使用的时pip list >>e:\piplist.txt 命令得到的模块列表
           for line in file:
                sa=line.split() 
                if(sa[1].replace(".","").isdigit()):                       
                    lines.append('=='.join(sa))    
        else:
            lines=file.readlines() #使用pip freeze > requirements.txt 得到模块列表
    for i in range(0,len(lines),1):        
        if(isDownload):            
            if(operate==0):
                newline='pip download '+lines[i].split('==')[0] +f' -i {modulesSource} \n'
            if(operate==4):
                newline='pip download '+lines[i].removesuffix('\r').removesuffix('\n') +f' -i {modulesSource} \n'
            lines[i]=newline
        else:
            if(isAutoInstall):
                newline='pip install '+lines[i] +f' -i {modulesSource} \n'
                if(isUpgrade):
                    newline=newline +'pip install '+lines[i].split('==')[0] +f' --upgrade -i {modulesSource} \n'
                lines[i]=newline
            else:
                if(isUpgrade):
                    lines[i]='pip install '+lines[i].split('==')[0]  +f' --upgrade -i {modulesSource} \n'
    with open(outputfile,'wt',encoding='utf-8') as file:
        file.writelines(lines)    
    if(autoExecuteBat):
        if(outputfile.endswith('.bat')):
            os.system(outputfile)
                    
    return True
  1. 自动升级部分 ,可以减少我们的手动操作,实现脱机安装的自动化,如下示例:
  2. 看到这里,施主和我肯定很有缘分了,至少我们又共同的目标和理想,还有共同的兴趣爱好。我们也都会进行抛砖引玉,希望我们的一点点努力,能够让这个世界更加美好一点点,然后聚沙成塔,集腋成裘,使得我们,我们的未来,充满憧憬和希冀,然后明天周一进行努力搬砖的动力,就会更加多一点点,没错,就是那个点点.
  3. 综合以上,我们实现一个整体的简单自动化模块脱机安装程序,基本完整代码如下:
#coding=utf-8
'''
author: lc.addverb
date:2022-07-17
version: vscode+python3.10
target:根据requirement.txt文件自动生成手动下载离线安装包
status:ok
注意:opencv版本要求opencv-python-headless<=4.5.4.60 :pip install opencv-python==4.5.4.60 
    若出现模块安装完毕但是不能使用时,需要uninstall模块后再次重新安装
从https://gitcode.net/mirrors/JaidedAI/EasyOCR?utm_source=csdn_github_accelerator 下载zip包,解压后在cmd中切换到当前路径,执行Python setup.py install 进行自动安装。然后可以使用。
使用pip install 模块名称,模块名称来安装缺乏的模块,建议使用国内源 -i https://pypi.douban.com/simple  -i https://pypi.tuna.tsinghua.edu.cn/simple
生成exe程序,请执行: pyinstaller  -F  -i logo.ico PythonModulesOperate.py 。在当前目录下的dist文件夹中生成一个文件的exe程序,使用指定的icon图标

'''
import os,sys,shutil
import zipfile,gzip,tarfile,rarfile
requirementFile='requirements.txt'
outputFile="./downloadofflinemodules.bat"
modulesSource='https://pypi.douban.com/simple'

def OperateOfflinePythonModules(inputFile='requirements.txt',outputfile="./downloadofflinemodules.bat" \
    ,operate=0,autoExecuteBat=False):
    '''根据选择自动生成python模块的批处理下载/安装/升级程序'''
    global requirementFile,modulesSource
    '''请输入选择的操作:
                 0. 生成手动下载python模块的批处理
                 1. 生成自动下载python模块的批处理
                 2. 生成自动下载python模块的批处理,并进行模块升级
                 3. 生成自动升级python模块的批处理
                 4. 生成手动下载指定版本python模块的批处理
                 5. 自动安装指定路径下的离线包
                 6. 生成本地计算机的pthon离线包文件:pip list >>file
                 7. 生成本地计算机的pthon离线包文件:pip freeze >>file 
                 8. 
    '''
    if operate==0:
        isDownload=True;isAutoInstall=False;isUpgrade=False
    elif operate==1:
        isDownload=False;isAutoInstall=True;isUpgrade=False
    elif operate==2:
        isDownload=False;isAutoInstall=True;isUpgrade=True
    elif operate==3:
        isDownload=False;isAutoInstall=False;isUpgrade=True
    elif operate==4:
        isDownload=True;isAutoInstall=False;isUpgrade=False
    elif operate==5:
        
        return instalModules(inputFile)
    elif (operate>=6 and operate <=7):
        if(operate==6):
            exe=f'pip list >>{outputfile}'
        elif(operate==7):
            exe=f'pip freeze >>{outputfile}'
        ret=os.system(exe)    
        return ret,True
    if inputFile=='':
        inputFile=requirementFile
    if outputfile=='':
        outputfile=outputFile
    lines=[]
    with open(inputFile,'rt',encoding='utf-8') as file:     
        firstline=file.readline()
        if(firstline.find('==')<0): #使用的时pip list >>e:\piplist.txt 命令得到的模块列表
           for line in file:
                sa=line.split() 
                if(sa[1].replace(".","").isdigit()):                       
                    lines.append('=='.join(sa))    
        else:
            lines=file.readlines() #使用pip freeze > requirements.txt 得到模块列表
    for i in range(0,len(lines),1):        
        if(isDownload):            
            if(operate==0):
                newline='pip download '+lines[i].split('==')[0] +f' -i {modulesSource} \n'
            if(operate==4):
                newline='pip download '+lines[i].removesuffix('\r').removesuffix('\n') +f' -i {modulesSource} \n'
            lines[i]=newline
        else:
            if(isAutoInstall):
                newline='pip install '+lines[i] +f' -i {modulesSource} \n'
                if(isUpgrade):
                    newline=newline +'pip install '+lines[i].split('==')[0] +f' --upgrade -i {modulesSource} \n'
                lines[i]=newline
            else:
                if(isUpgrade):
                    lines[i]='pip install '+lines[i].split('==')[0]  +f' --upgrade -i {modulesSource} \n'
    with open(outputfile,'wt',encoding='utf-8') as file:
        file.writelines(lines)    
    if(autoExecuteBat):
        if(outputfile.endswith('.bat')):
            os.system(outputfile)
                    
    return True
def instalModules(inPath=''):
    filenames=[name for name in os.listdir(inPath)
               if(os.path.isfile(os.path.join(inPath,name)))]
    for name in filenames:
        if(name.lower().endswith('.whl')):
            cmd='pip install '+os.path.join(inPath,name)
            os.system(cmd)
            print(f"指定的安装包/轮子{name}已经安装完毕。")
            pass
        elif(name.lower().endswith('.tar.gz')):
            ext='.tar.gz'
            f_name =os.path.join(inPath,os.path.splitext(name)[0].replace(".",""))# 获取输出文件路径和名称  
            #os.mkdir(f_name)
            tar_file = tarfile.open(os.path.join(inPath,name))  # 创建gzip对象     
            tmp=os.path.join(inPath)  #,name.removesuffix('.zip')            
            tar_file.extractall(path=tmp)
            tar_file.close()
            setup=os.path.join(tmp,name.replace(ext,""),'setup.py')
            #i=os.system(' cd ' +os.path.join(tmp,os.path.splitext(name)[0]))
            dirOld=os.getcwd()
            tmp=os.path.join(tmp,name.replace(ext,""))
            os.chdir(tmp) #切换到解压后的目录中
            dir=os.getcwd()
            cmd=f'python {setup} install' 
            os.system(cmd)
            os.chdir(dirOld)
            shutil.rmtree(tmp)
            print(f"指定的安装包/轮子{name}已经安装完毕。")
            pass
        elif(name.lower().endswith('.gz')):# 尚且不完善
            ext='.gz'
            f_name =os.path.join(inPath,os.path.splitext(name)[0].replace(".",""))# 获取输出文件路径和名称  
            #os.mkdir(f_name)
            g_file = gzip.GzipFile(os.path.join(inPath,name))  # 创建gzip对象       
            g_file.filename
            open(f_name, "wb+").write(g_file.read())  # gzip对象用read()打开后,写入open()建立的文件中。              
            g_file.close()   # 关闭gzip对象    
            dirOld=os.getcwd()        
            setup=os.path.join(f_name,'setup.py')
            cmd=f'python {setup} install' 
            os.system(cmd)
            os.chdir(dirOld)
            shutil.rmtree(tmp)
            print(f"指定的安装包/轮子{name}已经安装完毕。")
            pass
        elif(name.lower().endswith('.zip')):
            ext='.zip'
            zf=zipfile.ZipFile(os.path.join(inPath,name))
            tmp=os.path.join(inPath)  #,name.removesuffix('.zip')          
            zf.extractall(path=tmp)
            zf.close()
            #info=[lambda:os.path.split(n.lower()) for n in zf.filelist() ]
            #if(not info.index('setup.py')>=0):#没有setup.py文件
            #    continue
            setup=os.path.join(tmp,os.path.splitext(name)[0],'setup.py')
            #i=os.system(' cd ' +os.path.join(tmp,os.path.splitext(name)[0]))
            dirOld=os.getcwd()
            tmp=os.path.join(tmp,name.lower().replace(ext,""))
            os.chdir(tmp) #切换到解压后的目录中
            dir=os.getcwd()
            cmd=f'python {setup} install' 
            os.system(cmd)
            os.chdir(dirOld)
            shutil.rmtree(tmp)
            print(f"指定的安装包/轮子{name}已经安装完毕。")
            pass
            
    print("指定的安装包/轮子已经全部安装完毕。")
    return 
def un_gzfile(gz_path):
	# 异常处理
	try:
		# 压缩文件解压
		for f in  os.listdir(gz_path):
			if ".gz" in f:
				g = gzip.GzipFile(mode="rb", fileobj=open(gz_path+"\\"+f, 'rb'))
				open(gz_path+"\\"+f.replace(".gz",""), "wb").write(g.read())
	except Exception as e:
		print(e)
	else:
		print("文件解压成功!")
def getChoice():
    choice=input('''请输入选择的操作:
                 0. 根据requirements.txt,生成手动下载python模块的批处理
                 1. 根据requirements.txt,生成自动下载python模块的批处理
                 2. 根据requirements.txt,生成自动下载python模块的批处理,并进行模块升级到最新版本
                 3. 根据requirements.txt,生成自动升级python模块的批处理,升级到最新版本的批处理
                 4. 根据requirements.txt,生成手动下载指定版本python模块的批处理
                 5. 自动安装指定路径下已经下载的轮子/zip/gz离线包
                 6. 生成本地计算机的pthon离线包模块文件列表:pip list >>file
                 7. 生成本地计算机的pthon离线包模块文件列表:pip freeze >>file 
                 -1. 中断退出操作(默认输入)
                 
                 ''')
    maxChoice= 7
    if(choice==''):
        choice=-1
    choice=int(choice)
    if(choice==-1):
        print('选择退出操作。')
        sys.exit()
    if(choice>=0 and choice <=maxChoice):
        return choice,True
    else:
        return 0,False
def main():
    '''
    生成requirement.txt文件;
    根据requirement文件下载安装包/轮子到当前目录下;
    并且可以进行自动安装(.whl,.tar.gz,.zip),升级等奥做。
    '''
    print('运行本程序前,需要已经安装python,并且设置好python的path路径。只针对安装包进行操作。')
    print('isDownload=True,根据输入的文件列表,将下载的离线安装包/轮子保存到当前目录下。后续可以手动安装。')
    print('isAutoInstall=True,根据输入的文件列表,将自动从固定的站点("https://pypi.douban.com/simple")安装包/轮子。需要手动执行生成的bat文件')
    print('isUpgrade=True,根据输入的文件列表,将自动从固定站点("https://pypi.douban.com/simple")安装包/轮子的升级包。需要手动执行生成的bat文件')
    print('支持 pip freeze > requirements.txt 或者 pip list >>e:\piplist.txt 输出的模块列表文件格式')
    print('自动生成.bat文件,直接执行该文件即可进行自动安装/下载/升级,也可以使用autoExecuteBat参数进行生成bat后的自动执行')
    print('下面开始输入需要的参数:')
    
    choice,right=getChoice()
    while not right:
        choice,right=getChoice()
        
    infile=r'e:\piplist.txt'
    outfile=r'e:\requirements.bat'
    auto='n' #自动执行生成的bat文件
    if(choice>=0 and choice<=4):
        file=input(r"输入模块列表文件路径和文件名称(default='e:\piplist.txt'):")
        if file=='':
            file=infile
        infile=file
        file=input(r"输入.bat文件的路径和文件名称(default='e:\requirements.bat'):")
        if file=='':
            file=outfile
        outfile=file
        auto=input(r"自动执行生成的bat文件?y/n:")
    elif (choice==5):
        file=input(r"输入需要安装的python模块离线包文件的路径(default='e:\packages'):")
        if file=='':
            file='e:\packages'
        infile=file
    elif (choice>=6 and choice <=7):
        file=input(r"输入需要保存的当前计算机python模块列表文件的路径和文件名称(default='e:\requirements.txt'):")
        if file=='':
            file='e:\requirements.txt'
        outfile=file
    
    if(auto.lower()=='y'):
        isAutoRunBat=True
    else:
        isAutoRunBat=False
    
    OperateOfflinePythonModules(inputFile=infile,outputfile=outfile,operate=choice,autoExecuteBat=isAutoRunBat)
    
if __name__=='__main__':
    main()
    ```

‘’‘
14. 以上程序,已经程序粗略调试通过,作者本人不对代码承担任何承诺和风险,请各位自行斟酌。这个是本人的一个抛砖引玉,希望与各位大神可以一起把我们的工作和生活处理得更加丝滑顺畅,就像是我女票想要一个100平得小房子,我一点手就在浦东来个小别墅一样,那是不是真能把人从梦中幸福醒来?
好了,不多说,各位珍重,奋斗得路上我们风雨同行。(回头还是丢在git上,c站得开放性略显保守,就像是18上世纪得女人,总感觉怪怪的,但是又说不出什么来)
2022-7-17
’‘’
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值