2010-02-18 1 views
15

Я использую этот кусок кода в моем сценарии, чтобы определить, в кросс-платформенной способ, где именно он запускается с:Как я могу получить текущий каталог исполняемого файла в py2exe?

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

Довольно просто. Затем я продолжаю использовать SCRIPT_ROOT в других областях моего сценария, чтобы убедиться, что все относительно относительное. Моя проблема возникает, когда я запускаю ее через py2exe, потому что сгенерированный исполняемый файл не устанавливает __file__, поэтому мой скрипт ломается. Кто-нибудь знает, как исправить или обойти это?

+0

Существует более старый дублированный вопрос, но с меньшими ответами: [Определение пути приложения в Python EXE, сгенерированном pyInstaller] (http://stackoverflow.com/questions/404744) – olibre

ответ

2

Попробуйте это:

import os 
import sys 
os.path.realpath(os.path.dirname(sys.argv[0])) 
+1

По моему опыту, используя 'sys.argv [ 0] 'не имеет пути к нему, когда программа найдена через переменную PATH. – Ber

+0

@Ber, ... однако, «py2exe» - это особый случай, и во всех случаях он устанавливает полное значение. –

20

Вот py2exe documentation reference и здесь соответствующие пункты:

  • sys.executable установлен на полный путь к EXE-файла.
  • Первый элемент в sys.argv - полное имя исполняемого файла, остальные - аргументы командной строки.
  • sys.frozen только в исполняемом файле. Он имеет значение «console_exe» для исполняемого файла консоли, «windows_exe» для исполняемого файла без консоли и для «dll» для сервера inprocess dll.
  • __file__ не определен (вы можете использовать sys.argv [0] вместо)

Это не очевидно из этих Документов ли «ех-файл» и «исполняемые» одно и то же , и, таким образом, то же самое: sys.executable и sys.argv[0]. Глядя на код, который работал как script.py и py2exe_executable.exe последний раз, когда я должен был сделать это, я нахожу что-то вроде:

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

Как я уже говорил, что работал, но я не помню, почему я думал, что было необходимо вместо того, чтобы просто использовать sys.argv[0].

Использование только basis было подходящим для работы в руке (чтение файлов в этом каталоге). Для более постоянной записи разделите что-то вроде os.path.realpath(basis).

Обновление На самом деле сделал тест; бьет догадки и крепление кресла :-)

Реферат: Игнорировать sys.frozen, игнорировать sys.executable, перейти с sys.argv [0] безоговорочно.

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

=== установки.ру ===

from distutils.core import setup 
import py2exe 
setup(console=['foo.py']) 

=== Результаты ===

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 
+0

Я считаю, что sys.executable обычно указывает на сам интерпретатор python, чего вы хотите в py2exe, но не иначе. – prestomation

+0

@prestomation: Что такое «сам интерпретатор Python» в случае py2exe? Что вы подразумеваете под «но не иначе»? –

+0

«В противном случае» - это когда вы используете интерпретируемый файл, который является большинством сред. В случае py2exe я бы предположил, что интерпретатор - ваш py2exe, потому что он включен. Похоже, ваше последнее редактирование подтверждает это. – prestomation

8

py2exe не определяет __file__: http://www.py2exe.org/index.cgi/Py2exeEnvironment

ОП запросил py2exe дружественную версию:

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

Лучший ответ - определить, заморожен ли python в exe, py2exe имеет docum ентация на этом: 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() 

Так, питон является EAFP, вот 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__)) 

Ура!

+0

@ Вы правы ... Я должен был прочитать более внимательно. Лучше? – VertigoRay

+1

Это ТОЧНО, что задал вопрос. Спасибо за отличное решение. –

 Смежные вопросы

  • Нет связанных вопросов^_^