আমি সম্প্রতি অনুরূপ কিছু করার চেষ্টা করেছি এবং আমি এই উত্তরগুলি আমার ব্যবহারের ক্ষেত্রে (প্রকল্পের মূল সনাক্তকরণের জন্য প্রয়োজনীয় একটি বিতরণ গ্রন্থাগার) জন্য অপর্যাপ্ত পেয়েছি। মূলত আমি বিভিন্ন পরিবেশ এবং প্ল্যাটফর্মের সাথে লড়াই করছি এবং এখনও সর্বজনীন কিছু খুঁজে পাইনি।
স্থানীয় প্রকল্পে কোড
আমি এই উদাহরণটি দেখেছি এবং কয়েকটি জায়গায় ব্যবহার করেছি, জ্যাঙ্গো ইত্যাদি used
import os
print(os.path.dirname(os.path.abspath(__file__)))
যেমনটি সহজ, এটি কেবল তখনই কাজ করে যখন স্নিপেট থাকা ফাইলটি আসলে প্রকল্পের অংশ। আমরা প্রকল্প ডিরেক্টরিটি পুনরুদ্ধার করি না, পরিবর্তে স্নিপেটের ডিরেক্টরি
একইভাবে, অ্যাপ্লিকেশনটির প্রবেশের বাইরে থেকে ডেকে এলে sys.modules এপ্রক্রিয়া ভেঙে যায় , বিশেষত আমি দেখেছি যে কোনও শিশু থ্রেড ' মূল ' মডিউলটির সাথে সম্পর্ক ছাড়াই এটি নির্ধারণ করতে পারে না । চাইল্ড থ্রেড থেকে আমদানি প্রদর্শনের জন্য আমি স্পষ্টভাবে আমদানিটি কোনও ফাংশনের ভিতরে রেখেছি, এটিকে অ্যাপের শীর্ষ স্তরে নিয়ে যাওয়া এটিকে ঠিক করে দেবে py
app/
|-- config
| `-- __init__.py
| `-- settings.py
`-- app.py
app.py
#!/usr/bin/env python
import threading
def background_setup():
# Explicitly importing this from the context of the child thread
from config import settings
print(settings.ROOT_DIR)
# Spawn a thread to background preparation tasks
t = threading.Thread(target=background_setup)
t.start()
# Do other things during initialization
t.join()
# Ready to take traffic
settings.py
import os
import sys
ROOT_DIR = None
def setup():
global ROOT_DIR
ROOT_DIR = os.path.dirname(sys.modules['__main__'].__file__)
# Do something slow
এই প্রোগ্রামটি চালনা একটি বিশিষ্ট ত্রুটি উত্পাদন করে:
>>> import main
>>> Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python2714\lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python2714\lib\threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "main.py", line 6, in background_setup
from config import settings
File "config\settings.py", line 34, in <module>
ROOT_DIR = get_root()
File "config\settings.py", line 31, in get_root
return os.path.dirname(sys.modules['__main__'].__file__)
AttributeError: 'module' object has no attribute '__file__'
... সুতরাং থ্রেডিং-ভিত্তিক সমাধান
অবস্থান স্বাধীন
আগের মতো একই অ্যাপ্লিকেশন কাঠামো ব্যবহার করে সেটিংস.পি
import os
import sys
import inspect
import platform
import threading
ROOT_DIR = None
def setup():
main_id = None
for t in threading.enumerate():
if t.name == 'MainThread':
main_id = t.ident
break
if not main_id:
raise RuntimeError("Main thread exited before execution")
current_main_frame = sys._current_frames()[main_id]
base_frame = inspect.getouterframes(current_main_frame)[-1]
if platform.system() == 'Windows':
filename = base_frame.filename
else:
filename = base_frame[0].f_code.co_filename
global ROOT_DIR
ROOT_DIR = os.path.dirname(os.path.abspath(filename))
এটি ভাঙ্গা: প্রথমে আমরা সঠিকভাবে মূল থ্রেডের থ্রেড আইডিটি খুঁজতে চাই। পাইথন .4.৪+ থ্রেডিং লাইব্রেরিতে threading.main_thread()অবশ্য প্রত্যেকটি ৩.৪+ ব্যবহার করে না তাই আমরা এটির আইডির সাহায্যে মূল থ্রেডটি অনুসন্ধান করে সমস্ত থ্রেড অনুসন্ধান করি। যদি মূল থ্রেড ইতিমধ্যে উপস্থিত হয়ে থাকে, তবে এটি তালিকাভুক্ত হবে না threading.enumerate()। RuntimeError()আমি আরও ভাল সমাধান না পাওয়া পর্যন্ত এই ক্ষেত্রে একটি উত্থাপন করি।
main_id = None
for t in threading.enumerate():
if t.name == 'MainThread':
main_id = t.ident
break
if not main_id:
raise RuntimeError("Main thread exited before execution")
এর পরে আমরা মূল থ্রেডের প্রথম স্ট্যাক ফ্রেমটি পাই। সিপাইথন নির্দিষ্ট ফাংশনটি ব্যবহার করে sys._current_frames() আমরা প্রতিটি থ্রেডের বর্তমান স্ট্যাক ফ্রেমের একটি অভিধান পাই of তারপরে ব্যবহার করে inspect.getouterframes()আমরা মূল থ্রেড এবং খুব প্রথম ফ্রেমের জন্য পুরো স্ট্যাকটি পুনরুদ্ধার করতে পারি। কারেন্ট_মাইন_ফ্রেম = সিস ._কন্টেন_ফ্রেমস () [মেইন_আইডি] বেস_ফ্রেম = ইন্সপেক্ট.টাইটোটারফ্রেমস (কারেন্ট_মাইন_ফ্রেম) [- 1] অবশেষে, উইন্ডোজ এবং লিনাক্স বাস্তবায়নের মধ্যে পার্থক্যগুলি inspect.getouterframes()পরিচালনা করা দরকার। ক্লিন আপ ফাইল নাম ব্যবহার করে os.path.abspath()এবং os.path.dirname()জিনিসপত্র পরিষ্কার করুন।
if platform.system() == 'Windows':
filename = base_frame.filename
else:
filename = base_frame[0].f_code.co_filename
global ROOT_DIR
ROOT_DIR = os.path.dirname(os.path.abspath(filename))
এখন পর্যন্ত আমি এটি পাইথন 2.7 এবং উইন্ডোজে 3.6 পাশাপাশি ডাব্লুএসএলে পাইথন 3.4 এ পরীক্ষা করেছি
<ROOT>/__init__.pyরয়েছে?