泛舟海上 发表于 2022-1-3 01:58:10

python打包exe问题

使用pydub库写了一个音频转换的小程序,因为要调用ffmpeg,加了环境变量,直接IDLE跑没有问题,但是打包成exe之后就无法调用ffmpeg进行转换了。
不知道有没有人遇到了类似的情况,求帮助。{:5_109:}谢谢了!

泛舟海上 发表于 2022-1-3 01:58:46

打包用的pyinstaller,环境是同一台电脑测试的

hrpzcf 发表于 2022-1-3 02:31:00

调用ffmpeg的时候写相对路径,ffmpeg放主脚本同一目录下,在主脚本中用ffexec = os.getcwd() + "ffmpeg.exe"获取ffmpeg路径,如果有子脚本,在子脚本中调用ffmpeg,那子脚本要通过从主脚本取得ffexec变量的值的方式取得ffmpeg的路径。打包后,ffmpeg放在exe同目录下就可以了。

泛舟海上 发表于 2022-1-3 11:13:37

hrpzcf 发表于 2022-1-3 02:31
调用ffmpeg的时候写相对路径,ffmpeg放主脚本同一目录下,在主脚本中用ffexec = os.getcwd() + "ffmpeg.exe ...

{:5_109:} 我想过这种方式,但是它是pydub这个库里调用的exe,我路径要去改库函数写进去,然后再import进来用?

hrpzcf 发表于 2022-1-3 11:56:18

本帖最后由 hrpzcf 于 2022-1-3 12:15 编辑

我看了一下pydub的源码,他是通过系统环境变量找到ffmpeg的,你可以在你自己的脚本中调用pydub功能之前修改临时环境变量就可以了:
os.environ["PATH"] = "你的ffmpeg所在的目录路径" + os.pathsep + os.environ["PATH"]

泛舟海上 发表于 2022-1-3 12:15:02

hrpzcf 发表于 2022-1-3 11:56
我不了解pydub,它是通过什么方式找到ffmpeg的?它集成了的ffmpeg还是通过系统环境变量找到本机的ffmpeg?

是通过环境变量找的

hrpzcf 发表于 2022-1-3 12:15:30

泛舟海上 发表于 2022-1-3 12:15
是通过环境变量找的

楼上修改了,你看下

泛舟海上 发表于 2022-1-3 12:17:40

hrpzcf 发表于 2022-1-3 12:15
楼上修改了,你看下

好的,谢谢,我试一下

泛舟海上 发表于 2022-1-3 12:39:36

依旧不行,算了,后面再想办法试试吧,先继续学了,自己用起来直接idle先用着,下边是代码
from pydub import AudioSegment
from tkinter import *
import tkinter.filedialog as tf
from tkinter import ttk
import os




#转换函数
def trans_mp3_to_every(filepath,filepath_n,geshi_o,geshi):
    name='AudioSegment.from_'+geshi_o #参数名
    #print(name)
    #eval转换动态字符串为方法
    song=eval(name)(filepath)
   # print(filepath_n+'.'+geshi)
    song.export(filepath_n+'.'+geshi,format=geshi)



def main():
    #增加临时系统变量
    os.environ['PATH']=os.getcwd()+'\\bin'+os.pathsep+os.environ['PATH']


    root=Tk()

    root.title('转换音频')
    root.geometry('338x200')

    group =LabelFrame(root)
    group.grid(padx=5,pady=5)

    #选择待转换的文件
    Label(group,text='原文件:').grid(row=0,padx=5,pady=5,sticky=E)
    route_old=Entry(group)
    route_old.grid(row=0,column=1,padx=5,pady=5)
   
    def getroute_old():
      route_old.insert(0,tf.askopenfilename())

      
    Button(group,text='选择文件',command=getroute_old)\
    .grid(row=0,column=2,padx=5,pady=5)

    #选择目标保存的文件夹
    Label(group,text='目标文件夹:').grid(row=1,padx=5,pady=5,sticky=E)
    route_new=Entry(group)
    route_new.grid(row=1,column=1,padx=5,pady=5)
    def getroute_new():
      route_new.insert(0,tf.askdirectory())
    Button(group,text='选择文件夹',command=getroute_new)\
    .grid(row=1,column=2,padx=5,pady=5)

    #目标格式,设置下拉列表选择
    Label(group,text='目标格式:').grid(row=2,padx=5,pady=5,sticky='e')
    value=StringVar()
    value.set('ogg')
    values=['mp3','ogg','wav','aiff']
    geshi=ttk.Combobox(group,height=14,width=15,state='readonly'\
                     ,cursor='arrow',textvariable=value,values=values)
    geshi.grid(row=2,column=1,padx=5,pady=5,sticky='w')

    #定义选择列表事件,列表值设置为当前选中值
    def choose(event):
      value.set(value.get())

   #列表绑定选中事件   
    geshi.bind('<<ComboboxSelected>>',choose)



    #转换文件
    def transfile():
      geshi_o=route_old.get().split('.')[-1]
      filename_o=(route_old.get().split('/')[-1]).split('.')
      trans_mp3_to_every(route_old.get(),route_new.get()+'/'+filename_o,\
                           geshi_o,geshi.get())

   

    Button(group,text='开始转换',command=transfile).\
                                                 grid(row=3,columnspan=3,pady=20)

    mainloop()


if __name__=='__main__':
    main()

isdkz 发表于 2022-1-3 14:36:06

本帖最后由 isdkz 于 2022-1-3 14:37 编辑

泛舟海上 发表于 2022-1-3 12:39
依旧不行,算了,后面再想办法试试吧,先继续学了,自己用起来直接idle先用着,下边是代码

你用pyinstaller打包的话,可以加一个--add-data=bin;bin(--add-data=打包前的路径;打包后相对于项目的路径) 将ffmpeg给打包进去,也可以用pyi-makespec test.py文件生成.spec文件后,再修改.spec文件里面的datas选项,然后用pyinstaller test.spec打包。

泛舟海上 发表于 2022-1-3 16:18:55

isdkz 发表于 2022-1-3 14:36
你用pyinstaller打包的话,可以加一个--add-data=bin;bin(--add-data=打包前的路径;打包后相对于项 ...

谢了,这样也不行,后面研究下pydub的代码了,调用是它做的,感觉得指定它的调用路径

isdkz 发表于 2022-1-3 16:46:11

本帖最后由 isdkz 于 2022-1-3 17:04 编辑

泛舟海上 发表于 2022-1-3 16:18
谢了,这样也不行,后面研究下pydub的代码了,调用是它做的,感觉得指定它的调用路径

我拿你的代码试过了,是可以的

不过有一个问题,如果你是目录打包的话可以用os.getcwd()来拼接绝对路径,因为你的可执行文件就是跟bin在一个目录下。

但是你是文件打包就不可以了,因为你的可执行文件没有跟bin在一个目录,文件打包的方式其实运行的时候它也会解压一个临时目录出来的,你可以在资源管理器导航栏输%temp%进去查看

python因为要导包的原因,它会自动把这个路径加入sys.path的

所以,总的来说,你要用-F打包的话,你可以先import sys,然后添加环境变量改成   os.environ['PATH']=sys.path[-1]+'\\bin'+os.pathsep+os.environ['PATH']   这样打包后问题就可以解决了

泛舟海上 发表于 2022-1-3 21:44:46

isdkz 发表于 2022-1-3 16:46
我拿你的代码试过了,是可以的

不过有一个问题,如果你是目录打包的话可以用os.getcwd()来拼接绝对 ...

{:5_109:} 感谢,用-D打包解决了,-F加了这个环境变量还是有问题

isdkz 发表于 2022-1-3 22:24:08

本帖最后由 isdkz 于 2022-1-3 22:27 编辑

泛舟海上 发表于 2022-1-3 21:44
感谢,用-D打包解决了,-F加了这个环境变量还是有问题

默认就是-D的,-F我在这边也调试了把os.getcwd()换成 sys.path[-1] 是可以的,它把它解压后的路径加在了sys.path的最后,你可以到 %temp%(windows的临时文件夹下类似_MEI117762这种命名的文件夹里查看一下看看你的bin目录有没有打包进去了)你打包先不要隐藏那个控制台窗口,方便调试,可以print一下sys.path,调试成功后再隐藏控制台窗口打包https://fishc.com.cn/static/image/common/emp.gif
https://xxx.ilovefishc.com/album/202201/03/222157tattgvcwhctrhncc.png
https://fishc.com.cn/static/image/common/emp.gif

歌者文明清理员 发表于 2023-7-28 12:10:11

考古
页: [1]
查看完整版本: python打包exe问题