سؤال

لدي تطبيق بيثون. يتم تحميل ملفات التكوين (ومختلف الملفات الأخرى) عن طريق القيام بالأشياء مثل:

_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
CONFIG_DIR = os.path.join(_path, 'conf')

هذا يعمل بشكل جيد. ومع ذلك، عندما أحزم التطبيق مع Py2exe، تحدث أشياء سيئة:

  File "proj\config.pyc", line 8, in <module>
WindowsError: [Error 3] The system cannot find the path specified: 'C:\\proj\
\dist\\library.zip\\conf'

من الواضح أن هذا مسار غير صالح ... ما هي طريقة أكثر قوة للقيام بذلك؟ لا أريد تحديد المسارات المطلقة في البرنامج لأنه يمكن وضعه في مجلدات مختلفة. يجب أن أقول فقط "إذا وتقول أن اسم المجلد هو" Library.zip "، ثم انتقل إلى مستوى آخر لأسفل إلى مجلد" Dist "؟

لاحظ أن لدي التسلسلات الهرمية في الدليل المتداخلة جميلة ... على سبيل المثال، لدي وحدة Gui.utils.Images، المخزنة في "واجهة المستخدم الرسومية / Utils / images.py"، ويستخدم طريقها للوصول إلى "واجهة المستخدم الرسومية / الصور / موافق. PNG "، على سبيل المثال. في الوقت الحالي، ستحاول إصدار PY2EXE الوصول إلى "Proj / dist / library.zip / gui / images / ok.png"، أو شيء ما، والتي لن تعمل فقط.

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

المحلول

ما رأيك في استخدام المسارات النسبية لجميع الملفات المضمنة؟ أعتقد أنه ينبغي أن يكون من الممكن استخدام sys.path.append(".." + os.path.sep + "images") على سبيل المثال الخاص بك حول ok.png، ثم يمكنك فقط open("ok.png", "rb"). وبعد يجب على استخدام المسارات النسبية إصلاح المشكلات باستخدام ملف Library.zip الذي تم إنشاؤه بواسطة Py2exe، على الأقل هذا ما يفعله بالنسبة لي.

نصائح أخرى

النهج المعتاد للقيام بهذا النوع من الأشياء (إذا فهمت بشكل صحيح) هل هذا:

  1. تحقق sys.frozen، التي تعني py2exe تعيينها، باستخدام شيء مثل Getattr (SYS، "المجمدة"، ")
  2. إذا لم يتم تعيين ذلك، استخدم الطريقة المعتادة لأنك تعمل من المصدر
  3. إذا تم تعيينه، تحقق SYS.Executable لأن ذلك سيجرض لك إلى حيث يكون .EXE (بدلا من المكان الذي يوجد فيه python.exe، وهو ما يشير عادة إلى). استخدم شيئا مثل Os.path.dirname (SYS.Executable) ثم انضم إلى مساراتك النسبية للعثور على المجلدات الفرعية وما إلى ذلك

مثال:

frozen = getattr(sys, 'frozen', '')

if not frozen:
    # not frozen: in regular python interpreter
    approot = os.path.dirname(__file__)

elif frozen in ('dll', 'console_exe', 'windows_exe'):
    # py2exe:
    approot = os.path.dirname(sys.executable)

elif frozen in ('macosx_app',):
    # py2app:
    # Notes on how to find stuff on MAC, by an expert (Bob Ippolito):
    # http://mail.python.org/pipermail/pythonmac-sig/2004-November/012121.html
    approot = os.environ['RESOURCEPATH']

أو بعض البديل منها ... هذا الأخير يتعامل مع استخدام py2app. يمكنك تمديد هذا للبنائين الآخرين، إذا لزم الأمر.

استخدم Os.Path.dirname (Os.Path.abspath (sys.argv [0])) من تطبيق Py2exe، ستعمل بنفس الطريقة من البرنامج النصي Python (حتى تتمكن من الاختبار دون إنشاء EXE في كل مرة) و من إكس.

قد يكون هذا أفضل بكثير من استخدام المسارات النسبية لأنك لا داعي للقلق بشأن مكان تشغيل تطبيقك (.py أو .exe) من.

إليك حلاي (تم اختباره على Windows، Linux و Mac). يعمل أيضا في حالة بدء تشغيل التطبيق أو البرنامج النصي Python عبر رابط رمزي.

# Get if frozen
is_frozen = bool( getattr(sys, 'frozen', None) )

# Get path variable
path = sys.path if is_frozen else sys.argv

# Get nonempty first element or raise error
if path and path[0]:
    apppath = path[0]
elif is_frozen():
    raise RuntimeError('Cannot determine app path because sys.path[0] is empty.')
else:
    raise RuntimeError('Cannot determine app path in interpreter mode.')

# Make absolute (eliminate symbolic links)
apppath = os.path.abspath( os.path.realpath(apppath) )

# Split and return
appdir, appname = os.path.split(apppath)

يمكنني استخدام الخدعة التالية في Windows.
عندما يتم تجميد البرنامج في py2exe "قابل للتنفيذ" (أي my_application.exe.), dirname(__file__) إرجاع المجلد حيث يعمل البرنامج النصي Python الرئيسي الخاص بك. الغريب بما فيه الكفاية، هذا المجلد ليس هو المجلد الذي يحتوي على my_application.exe. لكن my_application.exe. بحد ذاتها.
لاحظ أن my_application.exe. ليس ملف ثنائي ولكن مجلد مضغوط (يمكنك فك ضغطه) يحتوي على Python Libs والبرامج النصية المترجمة الخاصة بك.
لهذا السبب os.path.dirname من الخاص بك __file__ هو في الحقيقة my_application.exe..

وبالتالي، يمنحك هذا الرمز الدليل الجذر لملفات التكوين الخاصة بك أو صورك (في حالة وجود تطبيق مجمد، والمجلد الذي يحتوي على PY2EXE القابل للتنفيذ، وإلا فإن المجلد من مكان تشغيل البرنامج النصي Python الخاص بك قيد التشغيل):

dirname = os.path.dirname(__file__)
if dirname.endswith('.exe'):
    dirname = os.path.split(dirname)[0]

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top