Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can i get the executable's current directory in py2exe?

Tags:

I use this bit of code in my script to pinpoint, in a cross-platform way, where exactly it's being run from:

SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))

Pretty simple. I then go on to use SCRIPT_ROOT in other areas of my script to make sure everything is properly relative. My problem occurs when I run it through py2exe, because the generated executable doesn't set __file__, therefore my script breaks. Does anyone know how to fix or work around this?

like image 813
Chris Lamberson Avatar asked Feb 18 '10 22:02

Chris Lamberson


People also ask

How do I check my Pyinstaller path?

To determine application path in a Python EXE generated by pyInstaller, we can check the sys. frozen property. If the value is True , then the script code is running in the exe file.

How do I get the Python application path?

getcwd() method. The os. getcwd() method is used for getting the Current Working Directory in Python. The absolute path to the current working directory is returned in a string by this function of the Python OS module.

Does py2exe work on Linux?

py2exe doesn't support on Linux or Mac, as it's aimed to create .exe files which is a Windows-unique format. You can download a Windows virtual machine on both Mac and Linux, use Wine or use a different tool like Pyinstaller on Linux, or py2app on Mac.


2 Answers

Here is the py2exe documentation reference and here are the relevant items:

  • sys.executable is set to the full pathname of the exe-file.
  • The first item in sys.argv is the full pathname of the executable, the rest are the command line arguments.
  • sys.frozen only exists in the executable. It is set to "console_exe" for a console executable, to "windows_exe" for a console-less gui executable, and to "dll" for a inprocess dll server.
  • __file__ is not defined (you might want to use sys.argv[0] instead)

It is not apparent from those docs whether "the exe-file" and "the executable" are the same thing, and thus whether sys.executable and sys.argv[0] are the same thing. Looking at code that worked for both script.py and py2exe_executable.exe last time I had to do this, I find something like:

if hasattr(sys, 'frozen'):
    basis = sys.executable
else:
    basis = sys.argv[0]
required_folder = os.path.split(basis)[0]

As I say that worked, but I don't recall why I thought that was necessary instead of just using sys.argv[0].

Using only basis was adequate for the job in hand (read files in that directory). For a more permanent record, split something like os.path.realpath(basis).

Update Actually did a test; beats guesswork and armchair pontification :-)

Summary: Ignore sys.frozen, ignore sys.executable, go with sys.argv[0] unconditionally.

Evidence:

=== 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'])

=== results ===

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
like image 98
John Machin Avatar answered Sep 21 '22 12:09

John Machin


Py2exe does not define __file__: http://www.py2exe.org/index.cgi/Py2exeEnvironment

The OP requested a py2exe friendly version of:

SCRIPT_ROOT = os.path.dirname(os.path.realpath(__file__))

The best answer is to determine if python is frozen in an exe, py2exe has documentation on this: 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()

Since, the python is EAFP, here's an EAFP version ...

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__))

Cheers!

like image 32
VertigoRay Avatar answered Sep 18 '22 12:09

VertigoRay