পাইথনে আমি কীভাবে বর্তমান সম্পাদিত ফাইলটির পথ পেতে পারি?


193

এটি একটি নবাগত প্রশ্নের মতো মনে হতে পারে, তবে তা নয়। কিছু সাধারণ পদ্ধতি সব ক্ষেত্রে কার্যকর হয় না:

sys.argv [0]

এর অর্থ হল ব্যবহার করা path = os.path.abspath(os.path.dirname(sys.argv[0])), তবে আপনি যদি অন্য ডিরেক্টরিতে পাইথন স্ক্রিপ্ট থেকে চালাচ্ছেন তবে এটি কার্যকর হয় না এবং এটি বাস্তব জীবনে ঘটতে পারে।

__file__

এর অর্থ ব্যবহার করা path = os.path.abspath(os.path.dirname(__file__)), কিন্তু আমি দেখতে পেয়েছি এটি কার্যকর হয় না:

  • py2exeএকটি নেই __file__গুণ, কিন্তু একটি হল কার্যসংক্রান্ত
  • আপনি যখন আইডিএল থেকে চালাবেন তখন execute()কোনও __file__বৈশিষ্ট্য নেই
  • ওএস এক্স 10.6 যেখানে আমি পাই NameError: global name '__file__' is not defined

অসম্পূর্ণ উত্তর সহ সম্পর্কিত প্রশ্ন:

আমি একটি জেনেরিক সমাধান খুঁজছি , একটি যা উপরের সমস্ত ব্যবহারের ক্ষেত্রে কাজ করবে।

হালনাগাদ

এখানে একটি টেস্টকেসের ফলাফল:

পাইথন এপিপি আউটপুট (উইন্ডোজে)

a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz

b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz

a.py

#! /usr/bin/env python
import os, sys

print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print

execfile("subdir/b.py")

subdir / b.py

#! /usr/bin/env python
import os, sys

print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print

গাছ

C:.
|   a.py
\---subdir
        b.py

উত্তর:


80

আপনি সরাসরি চালিত মূল স্ক্রিপ্টের অবস্থান নির্ধারণ করতে পারবেন না। সর্বোপরি, কখনও কখনও স্ক্রিপ্ট কোনও ফাইল থেকে আসে নি। উদাহরণস্বরূপ, এটি ইন্টারেক্টিভ দোভাষী বা গতিশীলভাবে উত্পন্ন কোড থেকে কেবল স্মৃতিতে সঞ্চিত হতে পারে।

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

some_path / module_locator.py:

def we_are_frozen():
    # All of the modules are built-in to the interpreter, e.g., by py2exe
    return hasattr(sys, "frozen")

def module_path():
    encoding = sys.getfilesystemencoding()
    if we_are_frozen():
        return os.path.dirname(unicode(sys.executable, encoding))
    return os.path.dirname(unicode(__file__, encoding))

some_path / main.py:

import module_locator
my_path = module_locator.module_path()

আপনার যদি বিভিন্ন ডিরেক্টরিতে বেশ কয়েকটি প্রধান স্ক্রিপ্ট থাকে তবে আপনার মডিউল_লোকেটরের একাধিক অনুলিপি লাগতে পারে।

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


2
আমি উল্লেখ করেছি যে ওএস 10.6 এ আমি ফাইলটিNameError: global name '__file__' is not defined ব্যবহার করতে পারি এবং এটি আইডলির অভ্যন্তরে নয়। মনে করুন এটি __file__কেবলমাত্র মডিউলগুলির মধ্যেই সংজ্ঞায়িত।
সোরিন

1
@ সোরিন সারবারিয়া: আমি কীভাবে এটি পেতে পারি তার সাথে আমি আমার উত্তর আপডেট করেছি।
ড্যানিয়েল স্টুটজবাখ

2
ধন্যবাদ, তবে বাস্তবে নিখোঁজ হওয়ার সমস্যাটির __file__ইউনিকোডের সাথে কোনও সম্পর্ক ছিল না। আমি জানি না কেন __file__সংজ্ঞায়িত করা হয়নি তবে আমি একটি জেনেরিক সমাধান খুঁজছি যা এটি সমস্ত ক্ষেত্রে কাজ করবে।
সোরিন

1
দুঃখিত, এটি সব ক্ষেত্রেই সম্ভব নয়। উদাহরণস্বরূপ আমি একটি wscript ফাইলের (পাইথন) ভিতরে waf.googlecode.com এ এটি করার চেষ্টা করি। এই ফাইলগুলি কার্যকর করা হয়েছে তবে সেগুলি মডিউল নয় এবং আপনি সেগুলি মডিউল তৈরি করতে পারবেন না (তারা উত্স ট্রি থেকে যে কোনও উপ-ডিরেক্টরি হতে পারে)।
সোমিন

1
এটি কি আপনাকে some_path/module_locator.pyপরিবর্তে লোকেশন দেবে না?
কেসব্যাশ

68

প্রথমত, আপনাকে inspectএবং থেকে আমদানি করা দরকারos

from inspect import getsourcefile
from os.path import abspath

এরপরে, আপনি যেখান থেকে উত্স ফাইলটি সন্ধান করতে চান সেখানে কেবল ব্যবহার করুন

abspath(getsourcefile(lambda:0))

সর্বোত্তম উত্তর. ধন্যবাদ.
দেওয়ান উইলিয়ামস

4
দুর্দান্ত উত্তর। ধন্যবাদ। এটি সবচেয়ে সংক্ষিপ্ত এবং বহনযোগ্য (উত্তর ওএস-এ চলমান) উত্তরও বলে মনে হয় এবং সমস্যাগুলির মুখোমুখি হয় না NameError: global name '__file__' is not defined( যেমন অন্য একটি সমাধান এর কারণ হয়েছিল)।
এডওয়ার্ড

আরেকটি সম্ভাবনা যা সমানভাবে খুব বেশী নেই lambda:_। এটি আমার পক্ষে কাজ করেছিল - নিশ্চিত নয় যে এটি সর্বদা কাজ করবে। lambda:0সম্ভবত কিছু অল্প পরিমাণে দ্রুত গতিতে চালিত হয় (বা সম্ভবত এত ছোট নয় ... এর জন্য 0লোড গ্লোবাল _বনামের জন্য তাত্ক্ষণিক লোড বা এমনকি আরও দ্রুত কিছু হতে পারে ?) বিতর্কযোগ্য এটি পড়াশোনা করা সহজ বা আরও চালাক / অস্পষ্ট হোক /
আর্টঅফ ওয়ারফেয়ার

আমি চেষ্টা করেছি এমন প্রায় প্রতিটি প্রস্তাবের মতো এটি কেবল আমার জন্য সিডাব্লুডি দেয়, আমি যে ডিরেক্টরি ফাইলটি চালাচ্ছি (ডিবাগিং) তা নয়।
জেমস

1
@ জেমস - এই কোডটি আপনি যে ফাইলটি চালাচ্ছেন তাতে চলে ... দৌড়া getsourcefile(lambda:0)অর্থহীন হবে এবং Noneআপনি যদি ইন্টারেক্টিভ প্রম্পটে এটি চালানোর চেষ্টা করেন তবেই ফিরে আসবে (যেহেতু এটি lambdaকোনও উত্স ফাইলে থাকবে না)) আপনি যদি জানতে চান ইন্টারেক্টিভ পরিবেশে যেখানে অন্য কোনও ক্রিয়াকলাপ বা অবজেক্টটি আসছে, সম্ভবত abspath(getsourcefile(thatFunctionOrObject))এটি আপনার পক্ষে আরও সহায়ক হবে?
আর্টঅফ ওয়ারফেয়ার

16

এই সমাধানটি এক্সিকিউটেবলের ক্ষেত্রেও শক্ত

import inspect, os.path

filename = inspect.getframeinfo(inspect.currentframe()).filename
path     = os.path.dirname(os.path.abspath(filename))

2
এটি সঠিক উত্তর হওয়া উচিত। এটি এমনকি এতে কাজ করে entry_point: console_script, তবে অন্য কোনও উত্তর দেয় না।
পোলভ

15

আমি একই ধরণের সমস্যায় পড়ছিলাম এবং আমি মনে করি এটি সমস্যার সমাধান করতে পারে:

def module_path(local_function):
   ''' returns the module path without the use of __file__.  Requires a function defined
   locally in the module.
   from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
   return os.path.abspath(inspect.getsourcefile(local_function))

এটি নিয়মিত স্ক্রিপ্টগুলির জন্য এবং নিষ্ক্রিয় অবস্থায় কাজ করে। আমি যা বলতে পারি তা অন্যের জন্য চেষ্টা করে দেখুন!

আমার সাধারণ ব্যবহার:

from toolbox import module_path
def main():
   pass # Do stuff

global __modpath__
__modpath__ = module_path(main)

এখন আমি __ ফাইল__ এর পরিবর্তে __ মডপথ__ ব্যবহার করি।


2
পিইপি 8 কোডিং স্টাইল গাইড অনুসারে, কারও কখনও ডাবল লিডিং এবং ট্রেলিং আন্ডারস্কোর যুক্ত নাম তৈরি করা উচিত নয় - তাই __modpath__নামকরণ করা উচিত। আপনারও সম্ভবত globalবিবৃতি দরকার নেই । অন্যথায় +1!
মার্টিনিউ

4
প্রকৃতপক্ষে আপনি কলটিতে সরাসরি স্থানীয় কার্যকারিতাটি সংজ্ঞায়িত করতে পারেন module_path()। অর্থাত module_path(lambda _: None)যা স্ক্রিপ্ট অন্যান্য বিষয়বস্তু উপর নির্ভর করে না এটা হয়।
Martineau

@ মার্টিনো: আমি আপনার পরামর্শটি গ্রহণ করেছি lambda _: Noneএবং এটি প্রায় দুই বছর ধরে ব্যবহার করেছি, তবে এখনই আমি আবিষ্কার করেছি যে আমি এটিকে নিখুঁতভাবে কমিয়ে দিতে পারি lambda:0_আদৌ কোন যুক্তি না দিয়ে আপনি যে ফর্মটি করেছিলেন সেটির কোনও উপেক্ষা যুক্তি দিয়ে পরামর্শ দেওয়ার কোনও বিশেষ কারণ আছে কি ? ন্যায়বিচারের Noneচেয়ে কোনও স্থানের উপসর্গের বিষয়ে আরও উন্নত কিছু আছে কি 0? তারা উভয়ই সমান ক্রিপ্টিক, আমার মনে হয়, কেবল একটি 8 টি অক্ষর দীর্ঘ এবং অন্যটি 14 টি অক্ষর দীর্ঘ।
আর্টঅফ ওয়ারফেয়ার

@ আর্টঅফওয়ারফেয়ার: এই দু'জনের মধ্যে পার্থক্য হ'ল এমন lambda _:একটি ফাংশন যা একটি যুক্তি গ্রহণ করে এবং একটিটি গ্রহণ lambda:করে না। ফাংশনটি কখনই ডাকা হয় না বলে কিছু যায় আসে না। একইভাবে কোনও রিটার্ন মান ব্যবহার করা হয় তা বিবেচনা করে না। আমি অনুমান করেছি যে আমি এটি বেছে নিয়েছিলাম Noneকারণ এমন সময় মনে হয়েছিল যে এটি একটি করণীয় কিছুই নয়, যাকে কখনও বলা যায় না-বলা ভাল ফাংশন। এর সামনের স্থানটি alচ্ছিক এবং আবার সেখানে কেবল উন্নত পাঠযোগ্যতার জন্য (সর্বদা PEP8 অনুসরণ করার চেষ্টা করা অভ্যাস-গঠন)।
মার্টিনিউ

@ মার্টিনো: এটি অবশ্যই কোনও অপব্যবহারের বিষয়, এটি এমন কোনও কিছুর lambdaজন্য ব্যবহার করা যা কখনই করা উচিত নয়। আপনি যদি পিইপি 8 অনুসরণ করেন তবে আমি মনে করি যে এটির জন্য সঠিক বিষয়বস্তু হবে passনা None, তবে এটিতে কোনও বিবৃতি দেওয়া বৈধ নয় lambda, সুতরাং আপনাকে কোনও মূল্য দিয়ে কিছু দিতে হবে। কয়েকটি বৈধ 2 অক্ষর জিনিষ আপনি রাখা থাকতে পারেন, তবে আমি মনে করি শুধুমাত্র বৈধ একক অক্ষর জিনিষ আপনি লাগাতে পারেন 0-9 হয় (বা একটি একক অক্ষর পরিবর্তনশীল নাম বাহিরে নির্ধারিত lambda।) আমি চিন্তা 0সেরা 0- এর অনস্তিত্ব ইঙ্গিত 9।
আর্টঅফ ওয়ারফেয়ার

6

সংক্ষিপ্ত উত্তরটি হ'ল আপনার পছন্দের তথ্য পাওয়ার কোনও গ্যারান্টিযুক্ত উপায় নেই , তবে অনুশীলনে প্রায় সবসময় কাজ করে এমন হিউরিস্টিক রয়েছে। আপনি হয়ত দেখতে পারেন আমি সি তে এক্সিকিউটেবলের অবস্থানটি কীভাবে খুঁজে পাব? । এটি সমস্যাটিকে সি দৃষ্টিকোণ থেকে আলোচনা করে তবে প্রস্তাবিত সমাধানগুলি সহজেই পাইথনে প্রতিলিপি হয়।


হ্যালো, আমার পতাকা প্রত্যাখ্যান করা হয়েছিল তাই আমি এখন মেটা নিয়ে আলোচনা শুরু করেছি: মেটা.স্ট্যাকওভারফ্লো
প্রশ্ন

তবে এই পৃষ্ঠায় ইতিমধ্যে সাধারণ কাজের উত্তর রয়েছে। আমার সমাধানটি ভালভাবে কাজ করে: stackoverflow.com/a/33531619/3787376
এডওয়ার্ড

5

আমার উত্তর কেন অবিশ্বাস্য ভেরিয়েবল ব্যবহার করে না সে সম্পর্কিত সম্পর্কিত তথ্যের জন্য প্যারেন্ট ফোল্ডার থেকে মডিউল আমদানি করা প্রশ্নের উত্তর দেখুন __file__। এই সহজ সমাধানটি মডিউল হিসাবে বিভিন্ন অপারেটিং সিস্টেমের সাথে ক্রস-সামঞ্জস্যপূর্ণ হওয়া উচিত osএবং inspectপাইথনের অংশ হিসাবে আসা উচিত।

প্রথমত, আপনাকে পরিদর্শন এবং ওএস মডিউলগুলির কিছু অংশ আমদানি করতে হবে ।

from inspect import getsourcefile
from os.path import abspath

এরপরে, আপনার পাইথন কোডে অন্য যেদিকে এটির প্রয়োজন নিচের লাইনটি ব্যবহার করুন:

abspath(getsourcefile(lambda:0))

কিভাবে এটা কাজ করে:

অন্তর্নির্মিত মডিউল থেকে os(নীচে বর্ণনা), abspathসরঞ্জামটি আমদানি করা হয়।

আমরা কোন সিস্টেমে আছি তার উপর নির্ভর করে ম্যাক, এনটি বা পিক্সিকের জন্য ওএস রুটিনগুলি।

তারপরে getsourcefile(নীচের বিবরণটি) অন্তর্নির্মিত মডিউল থেকে আমদানি করা হবে inspect

লাইভ পাইথন অবজেক্ট থেকে দরকারী তথ্য পান।

  • abspath(path) কোনও ফাইল পাথের পরম / পূর্ণ সংস্করণ প্রদান করে
  • getsourcefile(lambda:0)কোনওভাবে ল্যাম্বডা ফাংশন অবজেক্টের অভ্যন্তরীণ উত্স ফাইলটি পাওয়া যায়, তাই '<pyshell#nn>'পাইথন শেলটিতে ফিরে আসে বা পাইথন কোডের ফাইল পাথটি বর্তমানে কার্যকর করা হচ্ছে।

abspathএর ফলাফলটি ব্যবহার করে getsourcefile(lambda:0)নিশ্চিত হওয়া উচিত যে উত্পন্ন ফাইল পাথটি পাইথন ফাইলের সম্পূর্ণ ফাইল পাথ।
এই ব্যাখ্যাযুক্ত সমাধানটি মূলত উত্তর থেকে কোডের ভিত্তিতে তৈরি হয়েছিল পাইথনে আমি কীভাবে বর্তমান সম্পাদিত ফাইলটির পথ পেতে পারি?


হ্যাঁ, আমি ঠিক একই সমাধান নিয়ে এসেছি ... উত্তরগুলির চেয়ে আরও ভালভাবে বলা হয়েছে যে এটি নির্ভরযোগ্যভাবে করা যায় না ... যতক্ষণ না প্রশ্নটি আমার জিজ্ঞাসা না করে এটি কী তা ...
গ্রেডি প্লেয়ার

5

আপনি কেবল কল করেছেন:

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

পরিবর্তে:

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

abspath()আপনাকে sys.argv[0](আপনার কোডটিতে থাকা ফাইলের নামটি রয়েছে) এর পরম পথ দেয় এবং ফাইলের নাম dirname()ছাড়াই ডিরেক্টরি পথটি দেয়।


3

এটি ক্রস-প্ল্যাটফর্ম উপায়ে কৌশলটি করা উচিত (যতক্ষণ না আপনি দোভাষী বা কিছু ব্যবহার করছেন না):

import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))

sys.path[0]আপনার কলিং স্ক্রিপ্টটিতে যে ডিরেক্টরিটি রয়েছে (সেই স্ক্রিপ্টটি ব্যবহার করার জন্য মডিউলগুলির সন্ধান করার জন্য এটি প্রথম স্থান)। আমরা ফাইলটির নাম নিজেই শেষ sys.argv[0]করতে পারি (যা আমি দিয়েছিলাম os.path.basename)। os.path.joinক্রস প্ল্যাটফর্মের পথে কেবল তাদের একসাথে লাঠিচার্জ করুন। os.path.realpathকেবলমাত্র স্ক্রিপ্টের আসল নামটি পাওয়া গেলেও আমরা স্ক্রিপ্টের চেয়ে আলাদা নামের সাথে কোনও প্রতীকী লিঙ্ক পাই কিনা তা নিশ্চিত করে তোলে।

আমার কাছে ম্যাক নেই; সুতরাং, আমি এটি একটিও পরীক্ষা করিনি। এটি কাজ করে কিনা দয়া করে আমাকে জানান, যেমনটি মনে হয় এটি করা উচিত। আমি পাইথন ৩.৪ এর সাথে লিনাক্সে (জুবুন্টু) এটি পরীক্ষা করেছি। নোট করুন যে এই সমস্যার অনেকগুলি সমাধান ম্যাক্সে কাজ করে না (যেহেতু আমি এটি শুনেছি)__file__ ম্যাকসে উপস্থিত নেই)

মনে রাখবেন যে আপনার স্ক্রিপ্টটি যদি একটি প্রতীকী লিঙ্ক হয় তবে এটি আপনাকে যে ফাইলটি লিঙ্ক করবে (তার সাথে প্রতীকী লিঙ্কের পথ নয়) দেবে।


2

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

from pathlib import Path

# ...

Path(__file__)

আপনি parentআরও পথে যেতে কল করতে পারেন :

Path(__file__).parent

এই উত্তরটি __file__চলকটি ব্যবহার করে যা অবিশ্বাস্য হতে পারে (সর্বদা সম্পূর্ণ ফাইল পাথ নয়, প্রতিটি অপারেটিং সিস্টেমের উপর কাজ করে না ইত্যাদি) স্ট্যাকওভারফ্লো ব্যবহারকারীরা প্রায়শই উল্লেখ করেছেন। এটি অন্তর্ভুক্ত না করার উত্তর পরিবর্তন করা কম সমস্যা সৃষ্টি করবে এবং আরও ক্রস-সামঞ্জস্যপূর্ণ হবে। আরও তথ্যের জন্য, stackoverflow.com/a/33532002/3787376 দেখুন
এডওয়ার্ড

@ mrroot5 ঠিক আছে, সুতরাং আপনার মন্তব্য মুছে দিন।
গ্যাভরিল কোহেন

1

কোডটি যদি কোনও ফাইল থেকে আসছে তবে আপনি এর পুরো নামটি পেতে পারেন

sys._getframe().f_code.co_filename

আপনি হিসাবে ফাংশন নাম পুনরুদ্ধার করতে পারেন f_code.co_name


0

কেবল নিম্নলিখিতটি যুক্ত করুন:

from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)

বা:

from sys import *
print(sys.argv[0])

0

আমার সমাধানটি হ'ল:

import os
print(os.path.dirname(os.path.abspath(__file__)))

-1
import os
current_file_path=os.path.dirname(os.path.realpath('__file__'))

এটা কোন মানে নেই। প্রথমত, '__file__'কোনও স্ট্রিং হওয়া উচিত নয়, দ্বিতীয়, আপনি যদি করেন তবে __file__এটি কেবল এই ফাইলটির জন্য কাজ করবে যে কোডের এই লাইনটি রয়েছে, এবং যে ফাইলটি কার্যকর করা হয় না?
আন্দ্রেস স্টোরভিক স্ট্রুমান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.