سؤال

لدي طلب أن يقيم في مكان واحد .الملف py.لقد كنت قادرا على الحصول على pyInstaller إلى حزمة بنجاح إلى EXE على ويندوز.المشكلة يتطلب التطبيق .cfg دائما يجلس مباشرة بجوار تطبيق في نفس الدليل.

عادة يتم بناء مسار باستخدام التعليمات البرمجية التالية:

import os
config_name = 'myapp.cfg'
config_path = os.path.join(sys.path[0], config_name)

ومع ذلك ، يبدو sys.المسار فارغ عندما دعا من EXE الناتجة عن pyInstaller.نفس هذا السلوك يحدث عند تشغيل بايثون التفاعلي سطر الأوامر و محاولة جلب sys.المسار[0].

هل هناك أكثر ملموسة طريقة الحصول على مسار تطبيق قيد التشغيل حاليا بحيث يمكنني العثور على الملفات التي هي بالنسبة إلى ذلك ؟

هل كانت مفيدة؟

المحلول

ولقد وجدت الحل. تحتاج للتحقق مما إذا كان التطبيق يعمل كبرنامج نصي أو إكس المجمدة:

import os
import sys

config_name = 'myapp.cfg'

# determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
    application_path = os.path.dirname(sys.executable)
elif __file__:
    application_path = os.path.dirname(__file__)

config_path = os.path.join(application_path, config_name)

نصائح أخرى

وفقا الوثائق من pyInstaller ، اقترح طريقة استرداد مسار التطبيق على النحو التالي:

#!/usr/bin/python3
import sys, os
if getattr(sys, 'frozen', False):
    # If the application is run as a bundle, the pyInstaller bootloader
    # extends the sys module by a flag frozen=True and sets the app 
    # path into variable _MEIPASS'.
    application_path = sys._MEIPASS
else:
    application_path = os.path.dirname(os.path.abspath(__file__))

اختبار pyInstaller v3.2, ولكن هذا بالتأكيد كان يعمل على الإصدارات السابقة أيضا.

Soviut الحل لا يعمل, على الأقل ليس في الإصدارات الأخيرة من pyInstaller (لاحظ أن العملية سنوات عديدة).على سبيل المثال, على ماك, عند تجميع تطبيق في ملف واحد-حزمة ، sys.executable نقاط فقط على موقع جزءا لا يتجزأ من الأرشيف ، وهو لا الموقع حيث التطبيق يعمل في الواقع بعد pyInstaller محمل خلقت المؤقتة بيئة التطبيق.فقط sys._MEIPASS يشير بشكل صحيح إلى هذا الموقع.الرجوع إلى هذا doc-الصفحة لمزيد من المعلومات حول كيفية pyInstaller يعمل.

وأنا تقصير رمز قليلا.

import os, sys

if getattr(sys, 'frozen', False):
    application_path = os.path.dirname(sys.executable)
    os.chdir(application_path)

logging.debug('CWD: ' + os.getcwd())

ولكن، وأشار sys._MEIPASS إلى دليل على خطأ. أعتقد أنه يحتاج أيضا sys._MEIPASS + \app_name

os.path.dirname(sys.argv[0])

وهذا يعمل بالنسبة لي.

و__file__ تعمل من سطر الأوامر مع الثعبان قابل للتنفيذ. كما انه يعطي اسم الملف النصي دون المسار الفعلي في وضع المجمدة. ومع ذلك فإنه يعطي خطأ في الوضع التفاعلي.

وفيما يلي عمل لجميع وسائل ثلاثة:

import sys,os

config_name = 'myapp.cfg'

if getattr(sys, 'frozen', False):
    application_path = os.path.dirname(sys.executable)
    running_mode = 'Frozen/executable'
else:
    try:
        app_full_path = os.path.realpath(__file__)
        application_path = os.path.dirname(app_full_path)
        running_mode = "Non-interactive (e.g. 'python myapp.py')"
    except NameError:
        application_path = os.getcwd()
        running_mode = 'Interactive'

config_full_path = os.path.join(application_path, config_name)

print('Running mode:', running_mode)
print('  Appliction path  :', application_path)
print('  Config full path :', config_full_path)

وخرج في ثلاثة أوضاع مختلفة:

Running mode: Interactive
  Appliction path  : C:\Projects\MyAppDir
  Config full path : C:\Projects\MyAppDir\myapp.cfg

C:\Projects\MyAppDir>myapp.exe
Running mode: Frozen/executable
  Appliction path  : C:\Program Files\myapp
  Config full path : C:\Program Files\myapp\myapp.cfg

C:\Projects\MyAppDir>python myapp.py
Running mode: Non-interactive (e.g. 'python myapp.py')
  Appliction path  : C:\Projects\MyAppDir
  Config full path : C:\Projects\MyAppDir\myapp.cfg

C:\Projects\MyAppDir>

والعديد من الإجابات هنا ولكنني وجدت هذا الحل يعمل في معظم الحالات:

import os
import sys
import os.path as op
try:
    this_file = __file__
except NameError:
    this_file = sys.argv[0]
this_file = op.abspath(this_file)
if getattr(sys, 'frozen', False):
    application_path = getattr(sys, '_MEIPASS', op.dirname(sys.executable))
else:
    application_path = op.dirname(this_file)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top