Usando a excelente resposta de Max e Este post sobre adicionar arquivos de dados extras como imagens ou som e minha própria pesquisa / teste, descobri o que acredito ser a maneira mais fácil de adicionar esses arquivos.
Se você gostaria de ver um exemplo ao vivo, meu repositório está aqui no GitHub.
Nota: isso é para compilar usando o comando --onefile
ou -F
com pyinstaller.
Meu ambiente é o seguinte.
Resolvendo o problema em 2 etapas
Para resolver o problema, precisamos informar especificamente ao Pyinstaller que temos arquivos extras que precisam ser "agrupados" com o aplicativo.
Também precisamos usar um caminho 'relativo' , para que o aplicativo possa ser executado corretamente quando estiver sendo executado como um script Python ou um EXE congelado.
Com isso dito, precisamos de uma função que nos permita ter caminhos relativos. Usando a função que Max Postou , podemos resolver facilmente o caminho relativo.
def img_resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
Usaríamos a função acima assim, para que o ícone do aplicativo apareça quando o aplicativo estiver sendo executado como um Script OU EXE congelado.
icon_path = img_resource_path("app/img/app_icon.ico")
root.wm_iconbitmap(icon_path)
A próxima etapa é que precisamos instruir o Pyinstaller sobre onde encontrar os arquivos extras durante a compilação para que, quando o aplicativo for executado, eles sejam criados no diretório temporário.
Podemos resolver esse problema de duas maneiras, conforme mostrado na documentação , mas eu pessoalmente prefiro gerenciar meu próprio arquivo .spec, então é assim que faremos.
Primeiro, você já deve ter um arquivo .spec. No meu caso, consegui criar o que precisava executando pyinstaller
com args extras. Você pode encontrar args extras aqui . Por causa disso, meu arquivo de especificações pode parecer um pouco diferente do seu, mas estou postando tudo para referência depois de explicar as partes importantes.
add_files é essencialmente uma lista contendo tuplas, no meu caso eu só quero adicionar uma ÚNICA imagem, mas você pode adicionar vários ico's, png's ou jpg's usando('app/img/*.ico', 'app/img')
Você também pode criar outra tuplaadded_files = [ (), (), ()]
para ter várias importações
A primeira parte da tupla define que arquivo ou que tipo de arquivo você gostaria de adicionar, bem como onde encontrá-los. Pense nisso como CTRL + C
A segunda parte da tupla diz ao Pyinstaller para tornar o caminho 'app / img /' e colocar os arquivos nesse diretório RELATIVO a qualquer diretório temporário criado quando você executa o .exe. Pense nisso como CTRL + V
Ema = Analysis([main...
, eu configureidatas=added_files
, originalmente costumava ser,datas=[]
mas queremos que a lista de importações seja, bem, importada, então passamos nossas importações personalizadas.
Você não precisa fazer isso, a menos que queira um ícone específico para o EXE; na parte inferior do arquivo de especificações, estou dizendo ao Pyinstaller para definir o ícone do meu aplicativo para o exe com a opção icon='app\\img\\app_icon.ico'
.
added_files = [
('app/img/app_icon.ico','app/img/')
]
a = Analysis(['main.py'],
pathex=['D:\\Github Repos\\Processes-Killer\\Process Killer'],
binaries=[],
datas=added_files,
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='Process Killer',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True , uac_admin=True, icon='app\\img\\app_icon.ico')
Compilando para EXE
Sou muito preguiçoso; Não gosto de digitar coisas mais do que preciso. Criei um arquivo .bat no qual posso apenas clicar. Você não precisa fazer isso, este código será executado em um shell de prompt de comando sem ele.
Uma vez que o arquivo .spec contém todas as nossas configurações de compilação e args (opções também), só temos que fornecer esse arquivo .spec para o Pyinstaller.
pyinstaller.exe "Process Killer.spec"
a.datas += ...
) realmente me ajudou agora. a documentação do pyinstaller fala sobre o uso,COLLECT
mas não consegue colocar os arquivos no binário ao usar--onefile