史高治

新随笔 联系 管理
pyinstaller打包Python文件为exe:
 
1、下载并安装对应Python版本的pywin32.exe;
2、下载压缩软件upx.exe,放在Python的安装目录(若压缩后的exe文件打不开,或移除它重新打包,或使用3.5及以下版本的Python)
3、pip install pyinstaller
 
4、法①:在要打包的py文件所在目录进入cmd→pyinstaller -Fw 拖入那个py文件。
法②可批量打包: cmd进入py2exe.py所在目录,执行python py2exe.py。此py文件的内容如下:
from PyInstaller.__main__ import run
if __name__ == '__main__':
    #其他命令如设置图标:'--icon=Target.ico';是否压缩:'-upx'和'-noupx'
    pack = ['F:/New Download/fileSearch.py', '-Fw']    #首元素替换为被打包py文件的完整路径
    run(pack)
 
5、在dist目录下,取出已打包好的exe文件,此时可改个中文名。
 
注:Python文件若是窗体(如tkinter、pyqt等),打开exe后不想看到cmd黑框,打包命令是-Fw;无窗体的Python文件,需要看到cmd黑框,则打包命令是-F
****************************************分割线****************************************
tkinter窗体:
fnmatch.filter()方法,首参是文件列表;2参是unix风格的正则,如匹配后缀txt用*.txt,没有点;字母或汉字开头是[a-z一-龥]*;无\w语法。
 
Egの遍历目标文件夹下,文件名符合特征,且文件正文包含搜索内容的文件:
 
import threading,fnmatch,os,webbrowser
import tkinter as tk
from tkinter import messagebox,filedialog
 
def search():
    style=nameFeature.get() #不能用nameFeature、searchWord为名,致下次点按钮已覆盖
    word = searchWord.get()
    if not (style and word):
        messagebox.showerror('出错了','文件名特征和搜索词都不能为空')
        return
    listBox.delete(0,tk.END)   #返回本次搜索的结果之前,先清空上次的搜索列表
    traverse=os.walk(filedialog.askdirectory())
    for currentFolder,childFolders,childFiles in traverse:
        for file in fnmatch.filter(childFiles,style):  #文件名列表中,含有正则字串style的那些
            fileName=f'{currentFolder}/{file}'
            with open(fileName,'rb') as f:  #文件编码不一,换个思路,把搜索词转为二进制
                content=f.read()
            if word.encode() in content or word.encode('gbk') in content:
                listBox.insert(tk.END,fileName)
 
def openFile():
    fileName=listBox.get(listBox.curselection())
    os.startfile(fileName)  #或webbrowser.open(fileName),调用系统的默认程序来打开文件
 
def threadFunc(event):  #event对应bind()首参的按键等,如django各视图函数默用的request
    if listBox.curselection():    #列表框有内容并且被选中,才响应双击等事件
        t=threading.Thread(target=openFile)
        t.start()
 
#窗架、Label1+Entry1、Label2+Entry2、Button、listBox+Scrollbar
root=tk.Tk()
root.option_add('*font',('微软雅黑',18))    #设置窗体的默认字体;*表示(),**为{}
root.title('文件内容检索工具    作者:ChengY    QQ:904477955')
root.geometry('+240+200')    #960x360;长宽之间用字母x,连接屏幕位置用运算符+
 
tk.Label(root,text='文件名特征:').grid()  #要整齐排列,故布局用表格.grid(row,column)
nameFeature=tk.Entry(root,width=7);nameFeature.grid(row=0,column=1)
nameFeature.insert(tk.END,'*.txt') #后缀是py:*.py;文件名含中文:*[一-龥]*
 
tk.Label(root,text='搜索内容:').grid(row=0,column=2)
searchWord=tk.Entry(root);searchWord.grid(row=0,column=3)
searchWord.insert(tk.END,'python')  #给输入框设置个默认值
 
btn=tk.Button(root,text='要遍历的目录',command=search);btn.grid(row=0,column=4)
 
listBox=tk.Listbox(root,width=60)
xscroll=tk.Scrollbar(orient=tk.HORIZONTAL,command=listBox.xview)
xscroll.grid(row=2,columnspan=5,sticky=tk.E+tk.W)
yscroll=tk.Scrollbar(orient=tk.VERTICAL,command=listBox.yview)
yscroll.grid(row=1,column=5,sticky=tk.N+tk.S)
listBox['xscrollcommand'],listBox['yscrollcommand']=xscroll.set,yscroll.set
listBox.grid(row=1,columnspan=5)
listBox.bind('<Double-Button-1>',func=threadFunc)
 
root.mainloop()
******************分割线******************
Egの设计个性签名的窗体:
 
from tkinter import *
from tkinter import messagebox
import requests,re
from io import BytesIO
from PIL import Image
 
startUrl='http://www.uustv.com/'
 
def download():
    name=entry.get()
    if not name:
        messagebox.showinfo('提示', '请输入姓名!')
    data={'word':name,'sizes':'60','fonts':'jfcs.ttf','fontcolor':'#000000'}
    response=requests.post(url=startUrl,data=data)
    response.encoding='utf8'
    pic=re.findall('tmp/\d+?.gif',response.text)[0]
    imgUrl=startUrl+pic
    print(imgUrl)
    imgData=requests.get(imgUrl).content
    imgData=BytesIO(imgData)    #BytesIO把字节码转为内存中的文件
    Image.open(imgData).show()  #等1秒,待凹按钮复原后再关闭窗体
 
root=Tk()
root.title('个性签名')
root.geometry('480x360+600+300')
Label(root,text='hello,python',font=('华文中宋',20),background='yellow').grid()
entry=Entry(root,font=('微软雅黑',20))
entry.grid(row=0,column=1)
Button(root,text='设计签名',font=20,width=20,height=1,command=download).grid(row=2,column=1)
root.mainloop()
****************************************分割线****************************************
路径首之前要有r;路径至少俩\时,要把尾端的\变为\\
 
操作文件和目录:
 
import os,shutil
 
本脚本名=os.path.abspath(__file__)
连接路径=os.path.join('E:\\py','w.txt')
文件大小=os.path.getsize('E:/py/w.py') #单位:bytes
末斜杠分割=os.path.split('E:/py/a.py') #==os.path.dirname('E:/py/a.py')+basename…
后缀分割=os.path.splitext('E:/py/a.py') #盘符分割=os.path.splitdrive('E:/py/a.py')
文件存在否=os.path.isfile('E:/py/w.py') #文件夹存在否=os.path.isdir('E:/py')
 
os.makedirs('E:/x/y')   #创建目录,而os.mkdir得保证中间各路径已存在
os.remove('E:/w.py')    #删除文件
shutil.rmtree('E:/x/y')   #删除目录;若y为非空目录,则os.removedirs删不了
 
# 重命名,相较os.rename、os.replace,shutil.copy可跨磁盘,但复制文件夹得改用copytree
shutil.copy('E:/w.py','F:/x')    #有x则复制到其内,无则是复制为无后缀的文件x
shutil.copy2('E:/py/w.py','F:/x/a.txt') #copy只复制最后访问时间,copy2多复制个修改时间
shutil.copyfile('E:/py/w.py','F:/x/a.txt')  #最后的访问和修改时间都没复制,是执行此句的时间
shutil.copytree('E:/py','F:/t') #复制整个文件夹为另一目录,用此方法时目标目录不能已存在
shutil.move('E:/666','F:/v')    #同copy,有v则剪切至其内,无则改名为v;而且可操作文件夹
******************分割线******************
遍历某目录下所有包含州的Excel文件:
 
import os,pathlib
#t=os.listdir('D:\资料') #文件名不含路径,且不能遍历后代目录
t=[str(path) for path in pathlib.Path('D:\资料').rglob('*州*.xls*')]
******************分割线******************
文件夹批量改名,按照Excel首表的A列,改为对应的B列:
 
import os
 
baseDir='C:/Users/Administrator/Desktop/测试/'
 
from openpyxl import load_workbook  #打开已存在的工作簿
from openpyxl.styles import Font
wb=load_workbook(baseDir+'文件夹改名.xlsx')
ws=wb.worksheets[0]
LastRow=ws.max_row
 
for row in range(2,LastRow+1):
    os.rename(baseDir+str(ws['A'+str(row)].value),baseDir+str(ws['B'+str(row)].value))
******************分割线******************
域名的IP地址:
 
import socket
ip=socket.gethostbyname('example.com')
print(ip)
******************分割线******************
手机连电脑提示offline,可能其默认端口被其他应用挤占了:
 
①netstat -ano查各pid的ip:port(命令尾加|findstr pid号可只查此pid),看到手机adb的pid(任务管理器的详细信息选项卡下可查到)所对应的port为5037;②查看占用了5037端口的各进程:netstat -aon|findstr 5037;③根据干扰应用的pid(如为666)查看其名:tasklist /fi "PID eq 666";④用进程号结束此干扰应用:taskkill /pid 666 /f
****************************************分割线****************************************
操作压缩包:
 
import shutil   #添加整个文件夹到压缩包;zipfile只能用os.walk()遍历来逐一添加文件
shutil.make_archive('F:/hello','zip','F:/New Download/zhihuLive')   #首参压缩包名无后缀
shutil.unpack_archive('F:/hello.zip','F:/hello')    #支持zip、tar,不支持rar
 
import zipfile
with zipfile.ZipFile('F:/hello.rar','a') as f:  #追加模式打开压缩包;zip和rar都支持
    foldersAndFiles=f.namelist()
    fileContent=f.open(f.getinfo('zhihu/main.py')).read().decode()
    f.extractall('F:/hello')    #解压,同shutil.unpack_archive(源,至)
 
    #压缩包内存入本地文件用write,新建并写入内容用writestr;有的压缩类型不支持中文内容
    f.write('F:/练习.py','w/练习.py',zipfile.ZIP_DEFLATED)  #w是压缩包内的根目录,开头无/
    f.writestr('w/你好.txt','morning',zipfile.ZIP_DEFLATED)
****************************************分割线****************************************
批操作多台远程主机:
 
pip install fabric3
本地↔远程:local↔run(command),lcd↔cd(path),put(本,远)↔get,reboot()重启远程 ,
@runs_once常搭配local只在本机执行1次↔@task使函数名能被fab调用
fab参数:-H : 多台目标主机用,分割,-u用户名,-t超时,若名为fabfile.py可不用-f
 
from fabric.api import task,runs_once,local,run,env,put,cd
import os
 
#env.user='cy';env.password='111'    #各主机的用户名密码相同可用单数
#env.passwords={'Administrator@192.168.1.4:22':'666',}   #用户名密码不同用复数
 
env.hosts=['localhost',]    #只有复数
rar='"C:/Program Files/WinRAR/WinRAR.exe"'
 
@runs_once
def toRAR():
    local(rar+' a -ep1 -p123 "D:/666.rar" "E:/py/.idea"')   #rar压缩包的路径用/
 
def newFolder():
    command=local if env.host_string=='localhost' else run
    #with cd('C:/tests'):    #windows不能切换目录?
    if not os.path.isdir('C:/tests/world'):
        command('mkdir "C:/tests/world"')
    put("D:/666.rar","C:/tests/world/666.rar")
    command(rar+' x -p123 "C:/tests/world/666.rar" "C:/tests/world/"')
 
@task
def main():
    toRAR()    #加了@runs_once并且用的local,只在本机执行1次
    newFolder()    #普通函数,hosts里的各机都会执行1次
 
if __name__ == '__main__':
    os.system('chcp 65001') #cmd编码临时设为utf8
    os.system(f'fab -f {__file__} main')
posted on 2017-10-19 17:05  史高治  阅读(299)  评论(0编辑  收藏  举报