পাইথন - মূল প্রকল্প কাঠামোর পথ পান


127

আমি প্রকল্পের মূলের একটি কনফিগারেশন ফাইলের সাথে পাইথন প্রকল্প পেয়েছি। কনফিগারেশন ফাইলটি পুরো প্রকল্প জুড়ে কয়েকটি পৃথক ফাইলে অ্যাক্সেস করা দরকার।

: তাই এটা ভালো কিছু দেখায় <ROOT>/configuration.conf <ROOT>/A/a.py, <ROOT>/A/B/b.py(যখন বি, a.py এক্সেস কনফিগারেশন ফাইল)।

আমি যে প্রকল্পের ভিতরে আছি তাতে কোন ফাইলের উপর নির্ভর না করেই প্রকল্পের রুট এবং কনফিগারেশন ফাইলের সন্ধানের জন্য সবচেয়ে সহজ / সহজ উপায় কী? অর্থাৎ ব্যবহার না করে ../../? অনুমান করা ঠিক আছে যে আমরা প্রকল্পের মূলের নাম জানি।


নেই <ROOT>/__init__.pyরয়েছে?
মিগিলসন

হয় আপনার কনফিগারেশন ফাইলটি একটি অজগর মডিউল এবং আপনি কেবল একটি আমদানির বিবৃতি দিয়ে সহজেই এটি অ্যাক্সেস করতে পারবেন, হয় এটি পাইথন মডিউল নয় এবং আপনার এটি একটি পরিচিত স্থানে রাখা উচিত। উদাহরণস্বরূপ $ হোম / .মি_প্রজেক্ট / আমার_প্রজেক্ট.কনফ।
জন স্মিথ

@ জনস্মিথ অপশনাল - এটি একটি জেএসএন ফাইল। পথটি ব্যবহার করে আমার এটি অ্যাক্সেস করতে সক্ষম হওয়া দরকার। হ্যাঁ. সমস্ত ফোল্ডার এটি অন্তর্ভুক্ত।
শুকি

_ ধরে নেওয়া ঠিক আছে যে আমরা প্রকল্পের মূলের নাম জানি __ এর অর্থ কি আপনি প্রকল্পের পথ জানেন? তাহলে কি এটি কেবল os.path.join (পরিচিত_রূট_নাম, "কনফিগারেশন.কনফ") না?
tdelaney

এটি যদি কোনও ব্যবহারকারী কনফিগারেশন থাকে তবে আমি সাধারণত এর মতো কিছু ব্যবহার করি os.path.expanduser('~/.myproject/myproject.conf')। এটি ইউনিক্স এবং উইন্ডোজে কাজ করে।
জন স্মিথ

উত্তর:


157

জাজাঙ্গো এটি কীভাবে এটি করে তা আপনি এটি করতে পারেন: প্রকল্পের শীর্ষ স্তরে থাকা কোনও ফাইল থেকে প্রকল্প রুটের একটি পরিবর্তনশীল সংজ্ঞায়িত করুন। উদাহরণস্বরূপ, যদি আপনার প্রকল্পের কাঠামোর মতো দেখতে এটি হয়:

project/
    configuration.conf
    definitions.py
    main.py
    utils.py

ইন definitions.pyআপনি সংজ্ঞায়িত করতে পারেন (এটি প্রয়োজন import os):

ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) # This is your Project Root

সুতরাং, প্রকল্পের রুট পরিচিত হিসাবে, আপনি একটি পরিবর্তনশীল তৈরি করতে পারেন যা কনফিগারেশনের অবস্থানের দিকে নির্দেশ করে (এটি যে কোনও জায়গায় সংজ্ঞায়িত করা যেতে পারে, তবে একটি যৌক্তিক স্থানটি এমন স্থানে স্থাপন করা হবে যেখানে ধ্রুবকগুলি সংজ্ঞায়িত করা হয়েছে - যেমন definitions.py):

CONFIG_PATH = os.path.join(ROOT_DIR, 'configuration.conf')  # requires `import os`

তারপর, আপনি খুব সহজেই ইম্পোর্ট বিবৃতিটি (যেমন সঙ্গে ধ্রুবক (অন্যান্য ফাইল কোন ভাষায়) অ্যাক্সেস করতে পারেন utils.py): from definitions import CONFIG_PATH


1
এর মতো সংজ্ঞা.পি ফাইলটি অন্তর্ভুক্ত করার __init__.pyজন্য, মূল প্রকল্প ডিরেক্টরিতেও একটি ফাইল যুক্ত করা দরকার ? এটা কি সঠিক হওয়া উচিত? আমি অজগর দিয়ে শুরু করেছি এবং সেরা অনুশীলনের বিষয়ে নিশ্চিত নই। ধন্যবাদ।
akskap

3
@akskap: না, একটি __init__.pyপ্রয়োজন হবে না, যেমন যে ফাইল শুধুমাত্র যখন প্যাকেজ সংজ্ঞা প্রয়োজন বোধ করা হয়: ফাইল পাইথন যেমন প্যাকেজ ধারণকারী ডিরেক্টরি আচরণ করতে প্রয়োজন বোধ করা হয়; স্ট্রিংয়ের মতো একটি সাধারণ নাম সহ ডিরেক্টরিগুলি অনিচ্ছাকৃতভাবে মডিউল অনুসন্ধানের পথে পরে আসা বৈধ মডিউলগুলি আড়াল করা থেকে করা যায়। সবচেয়ে সহজ ক্ষেত্রে, খালি ফাইল হতে পারে তবে এটি প্যাকেজের জন্য আরম্ভকরণ কোডটি কার্যকর করতে পারে বা পরে বর্ণিত ভেরিয়েবল সেট করতে পারে দেখুন: docs.python.org/3/tutorial/modules.html#packages__init__.py__init__.py__all__
jrd1

আমি কৌতূহলী, স্টাইল বুদ্ধিমান, __init.py__রুট প্যাকেজটির সংজ্ঞাগুলিতে এই সংজ্ঞা যুক্ত করা গ্রহণযোগ্য বা ভ্রূকুয়া কিনা । এটি অন্য ফাইল তৈরি করা সাশ্রয় করবে এবং সেই সাথে এর উত্তম সিনট্যাক্সের অনুমতি দেবে from root_pack import ROOT_DIR, CONFIG_PATH
Johndt6

@ জনডট 6: কনভেনশনটি __init__.pyফাঁকা রাখা , তবে এটি কঠোরভাবে সত্য নয় (এটি সর্বোপরি একটি সম্মেলন)। : আরো এই দেখুন stackoverflow.com/questions/2361124/using-init-py
jrd1

1
@ জাভনূর: না - উদাহরণ হিসাবে আপনি উদ্ধৃত করেছেন, os.path.abspathএকটি স্ট্রিং কল করছে '__file__',। মনে রাখবেন এটি __file__আসলে একটি আমদানির বৈশিষ্ট্য যা পাইথন মডিউলগুলির জন্য সংজ্ঞায়িত। এই ক্ষেত্রে, __file__মডিউলটি লোড হওয়া পথটি ফেরত দেবে। এখানে আরও পড়ুন (মডিউল বিভাগটি দেখুন): ডকস.পিথন.আর.
/

61

অন্যান্য উত্তরগুলি প্রকল্পের শীর্ষ স্তরের কোনও ফাইল ব্যবহার করার পরামর্শ দেয়। আপনি pathlib.Pathএবং parent(পাইথন ৩.৪ এবং তার বেশি) ব্যবহার করলে এটি প্রয়োজনীয় নয় not নিম্নলিখিত ডিরেক্টরি কাঠামো বিবেচনা করুন যেখানে সমস্ত ফাইল বাদে README.mdএবং utils.pyবাদ দেওয়া হয়েছে।

project
   README.md
|
└───src
      utils.py
|   |   ...
|   ...

ইন utils.pyআমরা নিম্নলিখিত ফাংশন নির্ধারণ করুন।

from pathlib import Path

def get_project_root() -> Path:
    return Path(__file__).parent.parent

প্রকল্পের যে কোনও মডিউলে আমরা এখন নীচের মতো প্রকল্পের মূল পেতে পারি।

from src.utils import get_project_root

root = get_project_root()

উপকারিতা : যে কোনও মডিউল যা কল করে get_project_rootতা প্রোগ্রামের আচরণ পরিবর্তন না করেই সরানো যেতে পারে। মডিউলটি utils.pyসরানো হলেই আমাদের আপডেট করতে হবে get_project_rootএবং আমদানিগুলি (এটিকে স্বয়ংক্রিয় করতে রিফ্যাক্টরিং সরঞ্জামগুলি ব্যবহার করা যেতে পারে)।


2
মূলে যে কোনও মডিউল। মূলের বাইরে থেকে src.utils কল করা কার্যকর হবে না। আমি কি ভূল?
এরিজমান

নাম ' ফাইল ' সংজ্ঞায়িত হয় না, কেন?
লুক আরন

26

পূর্ববর্তী সমস্ত সমাধানগুলি আপনার যা প্রয়োজন মনে করি তার জন্য অতিরিক্ত জটিল বলে মনে হয় এবং প্রায়শই আমার পক্ষে কাজ করে না। নিম্নলিখিত এক-লাইন কমান্ডটি যা চায় তা করে:

import os
ROOT_DIR = os.path.abspath(os.curdir)

3
ডিরেক্টরিটির মূলটি কনফিগার করে রাখুন, ..! আপনি নিজেকে সিঙ্গলটন পেয়েছেন।
swdev

2
এই পদ্ধতিটি অনুমান করে আপনি অ্যাপ্লিকেশনটি যেভাবে রয়েছে তার মধ্যে থেকেই এটি চালাচ্ছেন। অনেক "ব্যবহারকারীর" কাছে একটি আইকন থাকে তারা ডেস্কটপ থেকে ক্লিক করে বা অন্য ডিরেক্টরি থেকে অ্যাপটি পুরোপুরি চালাতে পারে।
দেবপ্লেয়ার

23

"রুট" মডিউলটির পথ পেতে, আপনি ব্যবহার করতে পারেন:

import os
import sys
os.path.dirname(sys.modules['__main__'].__file__)

তবে আরও মজার বিষয় যদি আপনার শীর্ষ-সর্বাধিক মডিউলে কোনও কনফিগার "অবজেক্ট" থাকে তবে আপনি এটি পড়তে পারেন - এটি থেকে:

app = sys.modules['__main__']
stuff = app.config.somefunc()

1
এখানে osডিফল্টরূপে উপলব্ধ নয়। আমদানি করা দরকার os। সুতরাং লাইনটি যুক্ত করা import osউত্তরটিকে আরও সম্পূর্ণ করে তুলবে।
মোঃ আবু নাফী ইবনা জাহিদ

5
এটি সঞ্চালিত স্ক্রিপ্ট ধারণ করে এমন ডিরেক্টরি দেয়। উদাহরণস্বরূপ, চলমান যখন python3 -m topmodule.submodule.scriptএটি /path/to/topmodule/submoduleপরিবর্তে দেবে /path/to/topmodule
দানিজার

14

এটি অর্জনের একটি স্ট্যান্ডার্ড উপায় pkg_resourcesহ'ল setuptoolsপ্যাকেজের অংশ মডিউলটি ব্যবহার করা । setuptoolsএকটি ইনস্টল-সক্ষম পাইথন প্যাকেজ তৈরি করতে ব্যবহৃত হয়।

আপনি pkg_resourcesআপনার পছন্দসই ফাইলটির সামগ্রীগুলি স্ট্রিং হিসাবে ফিরিয়ে দিতে ব্যবহার করতে পারেন এবং আপনি pkg_resourcesআপনার সিস্টেমে পছন্দসই ফাইলটির আসল পথ পেতে ব্যবহার করতে পারেন ।

ধরা যাক আপনার কাছে একটি প্যাকেজ কল রয়েছে stackoverflow

stackoverflow/
|-- app
|   `-- __init__.py
`-- resources
    |-- bands
    |   |-- Dream\ Theater
    |   |-- __init__.py
    |   |-- King's\ X
    |   |-- Megadeth
    |   `-- Rush
    `-- __init__.py

3 directories, 7 files

এখন বলা যাক যে আপনি একটি মডিউল থেকে রাশ ফাইলটি অ্যাক্সেস করতে চান app.run। রাশটির pkg_resources.resouces_filenameপথ pkg_resources.resource_stringপেতে এবং রাশের সামগ্রীগুলি পেতে ব্যবহার করুন; thusly:

import pkg_resources

if __name__ == "__main__":
    print pkg_resources.resource_filename('resources.bands', 'Rush')
    print pkg_resources.resource_string('resources.bands', 'Rush')

আউটপুট:

/home/sri/workspace/stackoverflow/resources/bands/Rush
Base: Geddy Lee
Vocals: Geddy Lee
Guitar: Alex Lifeson
Drums: Neil Peart

এটি আপনার অজগর পথে সমস্ত প্যাকেজগুলির জন্য কাজ করে। সুতরাং আপনি যদি জানতে চান যে lxml.etreeআপনার সিস্টেমে কোথায় রয়েছে:

import pkg_resources

if __name__ == "__main__":
    print pkg_resources.resource_filename('lxml', 'etree')

আউটপুট:

/usr/lib64/python2.7/site-packages/lxml/etree

মুল বক্তব্যটি হ'ল আপনি আপনার সিস্টেমে ইনস্টল থাকা ফাইলগুলি (যেমন পিপ ইনস্টল এক্সএক্সএক্সএক্স বা ইয়াম -y ইনস্টল পাইথন-এক্সএক্সএক্স) এবং আপনি বর্তমানে যে মডিউলটিতে কাজ করছেন তার মধ্যে থাকা ফাইলগুলি অ্যাক্সেস করতে আপনি এই মানক পদ্ধতিটি ব্যবহার করতে পারেন।


1
আমি আপনার ব্যান্ড পছন্দ পছন্দ!
dylan_fan

3

চেষ্টা করুন:

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

1
এটি ঠিক আমার প্রয়োজন ছিল। সরল সমাধান, আমার জন্য কাজ করে কারণ আমার কাঠামোটি রুট-> কনফিগারেশন> কনফাইপি ছিল আমি কনফাইপিতে প্রকল্পের মূলটি সংজ্ঞায়িত করতে চেয়েছিলাম এবং রুটটি ফাইল থেকে ঠিক দুটি স্তর পর্যন্ত ছিল।
দানিয়াল আরশাদ

3

কোডের নীচে আপনার প্রকল্পের মূল পর্যন্ত আগমন করে

import sys
print(sys.path[1])

সুন্দর টিপ! আমি অবাক হয়েছি কেন আপনার উত্তরটি কেউ আমাকে
বাদ

ধন্যবাদ ডেভন সত্যই যে প্রশংসা !!
অর্পণ সায়নী

দুর্ভাগ্যবশত নয় যে, সহজ: পি ... আমার পূর্ণ সমাধান কটাক্ষপাত করা: stackoverflow.com/a/62510836/267719
daveoncode

2

আমি এই সমস্যার সমাধান না করে অবধি এই সমস্যার সাথে লড়াই করেছি। এটি আমার মতে সবচেয়ে পরিষ্কার সমাধান।

আপনার সেটআপ.পিতে "প্যাকেজগুলি" যুক্ত করুন

setup(
name='package_name'
version='0.0.1'
.
.
.
packages=['package_name']
.
.
.
)

আপনার পাইথন_স্ক্রিপ্ট.পি

import pkg_resources
import os

resource_package = pkg_resources.get_distribution(
    'package_name').location
config_path = os.path.join(resource_package,'configuration.conf')

ভার্চুয়াল পরিবেশ ব্যবহার এবং python3 setup.py installএটির সাথে প্যাকেজ ইনস্টল করা উত্স কোড ফোল্ডারের দিকে আর নির্দেশ করে না, বরং ভিতরে থাকা ডিমের দিকে ~./virtualenv/..../app.egg। সুতরাং আমি প্যাকেজ ইনস্টল মধ্যে কনফিগারেশন ফাইল অন্তর্ভুক্ত ছিল।
loxosceles

2

শুধু একটি উদাহরণ: আমি চালাতে চান runio.py মধ্যে থেকে helper1.py

প্রকল্প গাছ উদাহরণ:

myproject_root
- modules_dir/helpers_dir/helper1.py
- tools_dir/runio.py

প্রকল্পের মূলটি পান:

import os
rootdir = os.path.dirname(os.path.realpath(__file__)).rsplit(os.sep, 2)[0]

স্ক্রিপ্টে পাথ তৈরি করুন:

runme = os.path.join(rootdir, "tools_dir", "runio.py")
execfile(runme)

1

প্রকল্পের রুট ডিরেক্টরিতে আমার ভার্চুয়াল পরিবেশ (ভেন্ট) সহ একটি স্ট্যান্ডার্ড পাইচর্ম প্রকল্পটি ব্যবহার করে এটি আমার পক্ষে কাজ করেছে।

নীচের কোডটি সবচেয়ে সুন্দর নয়, তবে ধারাবাহিকভাবে প্রকল্পটির মূল পাবে। এটি VIRTUAL_ENVপরিবেশের ভেরিয়েবল থেকে উদ্যানের সম্পূর্ণ ডিরেক্টরি পাথ যেমন:/Users/NAME/documents/PROJECT/venv

এটি পরে /দুটি এলিমেন্টের সাথে একটি অ্যারে প্রদান করে শেষের দিকে পথটি বিভক্ত করে । প্রথম উপাদানটি হবে প্রকল্পের পথ যেমন eg/Users/NAME/documents/PROJECT

import os

print(os.path.split(os.environ['VIRTUAL_ENV'])[0])

3
এটি অ্যানাকোন্ডা বা পাইপেনভের মতো সেটআপগুলির সাথে কাজ করবে না, কারণ এই ক্ষেত্রে প্রকল্পের মধ্যে ভার্চুয়াল পরিবেশ নেই within
গ্রিপ

1

আমি সম্প্রতি অনুরূপ কিছু করার চেষ্টা করেছি এবং আমি এই উত্তরগুলি আমার ব্যবহারের ক্ষেত্রে (প্রকল্পের মূল সনাক্তকরণের জন্য প্রয়োজনীয় একটি বিতরণ গ্রন্থাগার) জন্য অপর্যাপ্ত পেয়েছি। মূলত আমি বিভিন্ন পরিবেশ এবং প্ল্যাটফর্মের সাথে লড়াই করছি এবং এখনও সর্বজনীন কিছু খুঁজে পাইনি।

স্থানীয় প্রকল্পে কোড

আমি এই উদাহরণটি দেখেছি এবং কয়েকটি জায়গায় ব্যবহার করেছি, জ্যাঙ্গো ইত্যাদি 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 এ পরীক্ষা করেছি


0

আপনি যদি অ্যানাকোন্ডা-প্রকল্পের সাথে কাজ করছেন, আপনি পরিবেশের পরিবর্তনশীল -> os.getenv ('PROJECT_ROOT') থেকে PROJECT_ROOT কে জিজ্ঞাসা করতে পারেন। এটি কেবল তখনই কাজ করে যদি স্ক্রিপ্টটি অ্যানাকোন্ডা-প্রকল্পের মাধ্যমে চালানো হয়।

যদি আপনি অ্যানাকোন্ডা-প্রকল্প দ্বারা চালিত আপনার স্ক্রিপ্টটি না চান, আপনি যে পাইথন ইন্টারপ্রেটার ব্যবহার করছেন তার এক্সিকিউটেবল বাইনারিটির পরম পাথটি জিজ্ঞাসা করতে পারেন এবং এনভিএস ডিরেক্টরি এক্সক্লুসিভ পর্যন্ত পাথ স্ট্রিংটি বের করতে পারেন। উদাহরণস্বরূপ: আমার কনডা এনভির অজগর দোভাষী এখানে অবস্থিত:

/ হোম / ব্যবহারকারী / project_root / envs / ডিফল্ট / bin / python-

# You can first retrieve the env variable PROJECT_DIR.
# If not set, get the python interpreter location and strip off the string till envs inclusiv...

if os.getenv('PROJECT_DIR'):
    PROJECT_DIR = os.getenv('PROJECT_DIR')
else:
    PYTHON_PATH = sys.executable
    path_rem = os.path.join('envs', 'default', 'bin', 'python')
    PROJECT_DIR = py_path.split(path_rem)[0]

এটি কেবল অ্যানাকোন্ডা-প্রকল্পের স্থির প্রকল্প কাঠামো সহ কনডা-প্রকল্পের সাথে কাজ করে


0

আমি বর্তমান প্রকল্পের পথটি আনার জন্য ../ পদ্ধতিটি ব্যবহার করেছি।

উদাহরণ: প্রজেক্ট 1 - ডি:। প্রকল্পগুলি

src

ConfigurationFiles

Configuration.cfg

পাথ = "../ src / ConfigurationFiles / Configuration.cfg"


0

লেখার সময়, অন্য সমাধানগুলির মধ্যে কোনওটিই খুব স্ব-অন্তর্নিহিত। তারা হয় পরিবেশের পরিবর্তনশীল বা প্যাকেজ কাঠামোর মডিউলের অবস্থানের উপর নির্ভর করে। 'জ্যাঙ্গো' সমাধানের সাথে শীর্ষের উত্তর আপেক্ষিক আমদানির প্রয়োজন পরে পরবর্তীটির শিকার হয়। এটি শীর্ষ স্তরে একটি মডিউল পরিবর্তন করতে অসুবিধা আছে।

শীর্ষ স্তরের প্যাকেজটির ডিরেক্টরি পথ অনুসন্ধানের জন্য এটি সঠিক পদ্ধতি হওয়া উচিত:

import sys
import os

root_name, _, _ = __name__.partition('.')
root_module = sys.modules[root_name]
root_dir = os.path.dirname(root_module.__file__)

config_path = os.path.join(root_dir, 'configuration.conf')

এটি এতে থাকা বিন্দুযুক্ত স্ট্রিংয়ের প্রথম উপাদানটি গ্রহণ করে __name__এবং এটি কী হিসাবে ব্যবহার করে sys.modulesযাতে শীর্ষ স্তরের প্যাকেজের মডিউল অবজেক্টটি ফিরে আসে works এর __file__বৈশিষ্ট্যটিতে ব্যবহারটি ছাঁটাই করার পরে আমরা যে পথটি চাই তা ধারণ /__init__.pyকরে os.path.dirname()

এই সমাধানটি স্বয়ংসম্পূর্ণ। এটি শীর্ষ-স্তরের __init__.pyফাইল সহ প্যাকেজের যে কোনও মডিউলে যে কোনও জায়গায় কাজ করে ।


আপনি কী কীভাবে নিজের সমাধান এবং এটি সমাধান হিসাবে তাদের ব্যবহার করতে পারেন সে সম্পর্কে একটি সংক্ষিপ্ত বিবরণ যুক্ত করতে পারেন?
LuRsT

0

আমাকে একটি কাস্টম সমাধান বাস্তবায়ন করতে হয়েছিল কারণ এটি আপনার মত সহজ মনে হয় না। আমার সমাধান স্ট্যাক ট্রেস পরিদর্শন ( inspect.stack()) + এর উপর ভিত্তি করে + sys.pathএবং পাইথন মডিউলের যেখানে ফাংশনটি আহ্বান করা হয়েছে তা বা দোভাষীর অবস্থান নির্বিশেষে খুব ভাল কাজ করছে (আমি এটি কবিতা শেল এবং অন্যান্যতে পাইচার্মে চালিয়ে চেষ্টা করেছি ... )। এটি মন্তব্য সহ সম্পূর্ণ বাস্তবায়ন:

def get_project_root_dir() -> str:
    """
    Returns the name of the project root directory.

    :return: Project root directory name
    """

    # stack trace history related to the call of this function
    frame_stack: [FrameInfo] = inspect.stack()

    # get info about the module that has invoked this function
    # (index=0 is always this very module, index=1 is fine as long this function is not called by some other
    # function in this module)
    frame_info: FrameInfo = frame_stack[1]

    # if there are multiple calls in the stacktrace of this very module, we have to skip those and take the first
    # one which comes from another module
    if frame_info.filename == __file__:
        for frame in frame_stack:
            if frame.filename != __file__:
                frame_info = frame
                break

    # path of the module that has invoked this function
    caller_path: str = frame_info.filename

    # absolute path of the of the module that has invoked this function
    caller_absolute_path: str = os.path.abspath(caller_path)

    # get the top most directory path which contains the invoker module
    paths: [str] = [p for p in sys.path if p in caller_absolute_path]
    paths.sort(key=lambda p: len(p))
    caller_root_path: str = paths[0]

    if not os.path.isabs(caller_path):
        # file name of the invoker module (eg: "mymodule.py")
        caller_module_name: str = Path(caller_path).name

        # this piece represents a subpath in the project directory
        # (eg. if the root folder is "myproject" and this function has ben called from myproject/foo/bar/mymodule.py
        # this will be "foo/bar")
        project_related_folders: str = caller_path.replace(os.sep + caller_module_name, '')

        # fix root path by removing the undesired subpath
        caller_root_path = caller_root_path.replace(project_related_folders, '')

    dir_name: str = Path(caller_root_path).name

    return dir_name

-1

এখানে অনেক উত্তর রয়েছে তবে আমি এমন সহজ কিছু আবিষ্কার করতে পারি না যা সমস্ত ক্ষেত্রেই কভার করে তাই আমাকেও আমার সমাধানের পরামর্শ দেওয়ার অনুমতি দিন:

import pathlib
import os

def get_project_root():
    """
    There is no way in python to get project root. This function uses a trick.
    We know that the function that is currently running is in the project.
    We know that the root project path is in the list of PYTHONPATH
    look for any path in PYTHONPATH list that is contained in this function's path
    Lastly we filter and take the shortest path because we are looking for the root.
    :return: path to project root
    """
    apth = str(pathlib.Path().absolute())
    ppth = os.environ['PYTHONPATH'].split(':')
    matches = [x for x in ppth if x in apth]
    project_root = min(matches, key=len)
    return project_root

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.