python - py3exe - ¿Cómo puedo obtener el directorio actual del ejecutable en py2exe?
python 3.7 to exe (3)
Utilizo este bit de código en mi script para señalar, de forma multiplataforma, desde donde se ejecuta exactamente:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
Bastante simple. Luego continúo usando SCRIPT_ROOT
en otras áreas de mi script para asegurarme de que todo sea correctamente relativo. Mi problema ocurre cuando lo ejecuto a través de py2exe, porque el ejecutable generado no establece __file__
, por lo tanto, mi script se rompe. ¿Alguien sabe cómo solucionar o solucionar esto?
Aquí está la referencia de documentación de py2exe y aquí están los elementos relevantes:
-
sys.executable
se establece en la ruta completa del archivo exe. - El primer elemento en
sys.argv
es la ruta completa del ejecutable, el resto son los argumentos de la línea de comando. -
sys.frozen
solo existe en el ejecutable. Se establece en "console_exe" para un ejecutable de consola, en "windows_exe" para un ejecutable gui sin consola y en "dll" para un servidor dll en proceso. -
__file__
no está definido (es posible que desee utilizar sys.argv [0] en su lugar)
No se desprende de esos documentos si "el archivo exe" y "el ejecutable" son la misma cosa, y por lo tanto si sys.executable
y sys.argv[0]
son la misma cosa. Mirando el código que funcionó para script.py y py2exe_executable.exe la última vez que tuve que hacer esto, encontré algo como:
if hasattr(sys, ''frozen''):
basis = sys.executable
else:
basis = sys.argv[0]
required_folder = os.path.split(basis)[0]
Como dije, eso funcionó, pero no recuerdo por qué pensé que era necesario en lugar de simplemente usar sys.argv[0]
.
Usar solo la basis
fue adecuado para el trabajo en cuestión (lea los archivos en ese directorio). Para un registro más permanente, divida algo como os.path.realpath(basis)
.
Actualización En realidad hizo una prueba; Supera las conjeturas y la pontificación del sillón :-)
Resumen: Ignore sys.frozen, ignore sys.executable, vaya con sys.argv [0] incondicionalmente.
Evidencia:
=== foo.py ===
# coding: ascii
import sys, os.path
print ''sys has frozen:'', hasattr(sys, ''frozen'')
print ''using sys.executable:'', repr(os.path.dirname(os.path.realpath(sys.executable)))
print ''using sys.argv[0]:'', repr(os.path.dirname(os.path.realpath(sys.argv[0] )))
=== setup.py ===
from distutils.core import setup
import py2exe
setup(console=[''foo.py''])
=== resultados ===
C:/junk/so/py2exe>/python26/python foo.py
sys has frozen: False
using sys.executable: ''C://python26''
using sys.argv[0]: ''C://junk//so//py2exe'' # where foo.py lives
C:/junk/so/py2exe>dist/foo
sys has frozen: True
using sys.executable: ''C://junk//so//py2exe//dist''
using sys.argv[0]: ''C://junk//so//py2exe//dist'' # where foo.exe lives
Prueba esto:
import os
import sys
os.path.realpath(os.path.dirname(sys.argv[0]))
Py2exe no define __file__
: http://www.py2exe.org/index.cgi/Py2exeEnvironment
El OP solicitó una versión amigable de py2exe de:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
La mejor respuesta es determinar si Python está congelado en un archivo ejecutable, py2exe tiene documentación sobre esto: http://www.py2exe.org/index.cgi/HowToDetermineIfRunningFromExe
import imp, os, sys
def main_is_frozen():
return (hasattr(sys, "frozen") or # new py2exe
hasattr(sys, "importers") # old py2exe
or imp.is_frozen("__main__")) # tools/freeze
def get_main_dir():
if main_is_frozen():
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.realpath(__file__))
SCRIPT_ROOT = get_main_dir()
Dado que, el python es EAFP , aquí hay una versión de EAFP ...
try:
if sys.frozen or sys.importers:
SCRIPT_ROOT = os.path.dirname(sys.executable)
except AttributeError:
SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))
¡Aclamaciones!