পাইথন 3 এ ফাঁসির বিকল্প কী?


352

দেখে মনে হচ্ছে যে তারা পাইথন 3 এ দ্রুত মুছে ফেলার মাধ্যমে কোনও স্ক্রিপ্ট দ্রুত লোড করার সমস্ত সহজ উপায় বাতিল করে দিয়েছে execfile()

আমি কি অনুপস্থিত কোন স্পষ্ট বিকল্প আছে?


1
reloadফিরে এসেছে, imp.reload৩.২ থেকে।
ডুগল

18
আপনি যদি পাইথন ব্যবহার করছেন তবে আইপিথনটি ইন্টারেক্টিভভাবে বিবেচনা করুন: %run script_nameপাইথনের সমস্ত সংস্করণে কাজ করে।
মাইকেল

1
যেহেতু 3.4 impহ'ল importlib (যা অবশ্যই আমদানি করা উচিত): importlib.reload(mod_name)আমদানি এবং সম্পাদন করে mod_name
পি। ওয়ার্মার

3
রানফাইল ("filename.py") এর সাথে কী সমস্যা?
মৌসুমার

1
ধন্যবাদ @ মৌসুমার !! আমি যথাযথভাবে এর কার্যকারিতাটি সন্ধান runfile()করছিলাম যেহেতু আমাকে পাইথন স্ক্রিপ্টটি চালানোর দরকার ছিল যা তার নিজস্ব নামস্থানে চালিত করে ( কলিং নেমস্পেসে কার্যকর করার বিপরীতে )। আমার অ্যাপ্লিকেশন: অ্যাট্রিবিউটটি sys.pathব্যবহার করে সিস্টেম স্ক্রিপ্টে ( ) কলযুক্ত স্ক্রিপ্টের ডিরেক্টরি যুক্ত করুন __file__: আমরা execfile()পাইথন 3 ( exec(open('file.py').read())) তে যদি এর ব্যবহার করি বা এর সমতুল্য হয় তবে অন্তর্ভুক্ত স্ক্রিপ্টটি কলিং নেমস্পেসে চালিত হয় এবং এইভাবে কলিং ফাইলের নামের সাথে __file__সমাধান হয় ।
মাস্ত্রপি

উত্তর:


389

ডকুমেন্টেশন অনুযায়ী , পরিবর্তে

execfile("./filename") 

ব্যবহার

exec(open("./filename").read())

দেখা:


54
কোনও ধারণা তারা কেন এমন কাজ করবে? এটি আগের চেয়ে অনেক বেশি ভার্বোজ। এছাড়াও, পাইথন 3.3 এ এটি আমার পক্ষে কাজ করে না। আমি এক্সিকিউট করার সময় আমি "এ জাতীয় কোনও ফাইল বা ডিরেক্টরি" পাই না (খোলা ('./ some_file')। পড়ুন ())। আমি '.py' এক্সটেনশন সহ এবং './' বাদ দিয়েও চেষ্টা করেছি
জোয়িসি

25
অপেক্ষাকৃত কম তুচ্ছভাবে, এক্সিকিপাইল () হিসাবে ব্যতিক্রমগুলি উত্থাপিত হওয়ার সময় এটি লাইন নম্বর সরবরাহ করে না।
কেডিএন

35
closeআপনারও সেই ফাইল হ্যান্ডেলটি দরকার । আরেকটি কারণ পাইথন 2. থেকে পরিবর্তন অপছন্দ
Rebs

3
@ র‌্যাবস, উদাহরণস্বরূপ আপনার ফাইল হ্যান্ডেলটি বন্ধ করার দরকার নেই, এটি স্বয়ংক্রিয়ভাবে সম্পন্ন হবে (কমপক্ষে নিয়মিত সিপিথনে)
টিহো

4
CPython বস্তু @Rebs আবর্জনা-সংগৃহীত যত তাড়াতাড়ি তাদের রেফারেন্স গণনা 0 যায় হয়, শুধুমাত্র সার্কুলার রেফারেন্স এই (দেরী হতে পারে stackoverflow.com/questions/9449489/... )। সেক্ষেত্রে পড়া () রিটার্নের পরে ঠিক হওয়া উচিত। এবং ফাইল অবজেক্টগুলি মুছে ফেলা বন্ধ রয়েছে (এনবি: আমি বুঝতে পারছি যে এই লিঙ্কটি স্পষ্টভাবে "সর্বদা ফাইলগুলি বন্ধ করুন" বলে, যা সাধারণভাবে অনুসরণ করা সত্যই ভাল অভ্যাস)
তিহো

219

আপনি কেবল ফাইলটি পড়বেন এবং কোডটি নিজে সম্পাদন করবেন। 2to3 বর্তমান প্রতিস্থাপন

execfile("somefile.py", global_vars, local_vars)

যেমন

with open("somefile.py") as f:
    code = compile(f.read(), "somefile.py", 'exec')
    exec(code, global_vars, local_vars)

(সংকলন কলটি কঠোরভাবে প্রয়োজন হয় না, তবে এটি ফাইলের নামটি কোড অবজেক্টকে ডিবাগিংটি আরও সহজ করে তোলে।

দেখা:


3
এটি আমার পক্ষে কাজ করে। তবে, আমি লক্ষ্য করেছি যে আপনি স্থানীয় এবং বৈশ্বিক যুক্তিগুলি ভুল ক্রমে লিখেছেন। এটি আসলে: এক্সিকিউট (অবজেক্ট [, গ্লোবালস [, স্থানীয়রা]])। অবশ্যই যদি আপনার আর্গুমেন্টগুলি আসলভাবে উল্টে যায় তবে 2to3 আপনি যা বলেছিলেন তা হ'ল উত্পন্ন করবে। :)
নাথান শিভলি-স্যান্ডার্স

3
এটি আবিষ্কার করে সন্তুষ্ট হয়েছিল যে, আপনি যদি গ্লোবাল_ভার এবং স্থানীয়_ভারগুলি বাদ দিতে পারেন তবে পাইথন 3 প্রতিস্থাপনটি পাইথন 2 এর অধীনেও কাজ করে। যদিও execপাইথন 2-তে একটি বিবৃতি, exec(code)প্যারেন্সগুলি কেবল উপেক্ষা করার কারণে এটি কাজ করে।
ম্যাডমন্ডস

2
সংকলন ব্যবহারের জন্য +1। আমার "somefile.py"থাকা inspect.getsourcefile(lambda _: None)যা সংকলন ব্যতীত ব্যর্থ হয়েছিল, কারণ inspectমডিউলটি নির্ধারণ করতে পারে নি যে কোডটি কোথা থেকে আসছে।
আর্টঅফ ওয়ারফেয়ার

16
এটা ... সত্যিই কুরুচিপূর্ণ। কোন ধারণা কেন তারা 3.x তে এক্সিকিফাইল () থেকে মুক্তি পেয়েছে? এক্সিকিফাইল কমান্ডলাইন আরগগুলি পাস করাও সহজ করে তুলেছিল।
অ্যানকোডিয়াল

3
open("somefile.py")যদি somefile.pyকোনও অক্ষর এনকোডিং থেকে আলাদা হয় তবে এটি ভুল হতে পারে locale.getpreferredencoding()tokenize.open()পরিবর্তে ব্যবহার করা যেতে পারে।
jfs

73

যদিও এর exec(open("filename").read())বিকল্প হিসাবে প্রায়শই দেওয়া হয় execfile("filename"), এটি execfileসমর্থন করে এমন গুরুত্বপূর্ণ বিশদটি বাদ দেয় ।

পাইথন 3.x এর জন্য নিম্নলিখিত ফাংশনটি যতটা কাছাকাছি আমি সরাসরি কোনও ফাইল চালানোর মতো আচরণ করতে পারি। যে ম্যাচ চলছে python /path/to/somefile.py

def execfile(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
    globals.update({
        "__file__": filepath,
        "__name__": "__main__",
    })
    with open(filepath, 'rb') as file:
        exec(compile(file.read(), filepath, 'exec'), globals, locals)

# execute the file
execfile("/path/to/somefile.py")

মন্তব্য:

  • এনকোডিংয়ের সমস্যাগুলি এড়াতে বাইনারি রিডিং ব্যবহার করে
  • ফাইলটি বন্ধ করার গ্যারান্টিযুক্ত (পাইথন 3.x এটি সম্পর্কে সতর্ক করে)
  • সংজ্ঞায়িত করে __main__, কিছু স্ক্রিপ্টগুলি মডিউল হিসাবে লোড হচ্ছে কিনা তা যাচাই করার জন্য এটির উপর নির্ভর করে।if __name__ == "__main__"
  • সেট __file__ব্যতিক্রম বার্তাগুলির জন্য সুন্দর এবং কিছু অন্যান্য স্ক্রিপ্টগুলি __file__তাদের সম্পর্কিত অন্যান্য ফাইলের পাথ পেতে ব্যবহার করে।
  • Doesচ্ছিক গ্লোবাল এবং স্থানীয় আর্গুমেন্ট নেয়, সেগুলিকে স্থানে পরিবর্তিত execfileকরে - যাতে আপনি চলার পরে ভেরিয়েবলগুলি পড়ে সংজ্ঞায়িত যে কোনও ভেরিয়েবল অ্যাক্সেস করতে পারেন।

  • পাইথন 2 এর বিপরীতে এটি বর্তমান নাম স্থানটি ডিফল্টরূপে পরিবর্তন execfileকরে না । তার জন্য আপনাকে স্পষ্টতই globals()& এ প্রবেশ করতে হবে locals()


68

পাইথন- ডেভেল মেলিংলিস্টে সম্প্রতি প্রস্তাবিত হিসাবে , রান্পি মডিউলটি একটি কার্যকর বিকল্প হতে পারে। এই বার্তাটি উদ্ধৃত:

https://docs.python.org/3/library/runpy.html#runpy.run_path

import runpy
file_globals = runpy.run_path("file.py")

এর মধ্যে সূক্ষ্ম পার্থক্য রয়েছে execfile:

  • run_pathসর্বদা একটি নতুন নেমস্পেস তৈরি করে। এটি কোডটি একটি মডিউল হিসাবে কার্যকর করে, তাই গ্লোবাল এবং স্থানীয়দের মধ্যে কোনও পার্থক্য নেই (যার কারণে কেবলমাত্র একটি init_globalsযুক্তি রয়েছে)। গ্লোবালগুলি ফিরিয়ে দেওয়া হয়েছে।

    execfileবর্তমান নেমস্পেস বা প্রদত্ত নেমস্পেসে সম্পাদিত। শব্দার্থবিদ্যা localsএবং globalsযদি দেওয়া হয় তবে শ্রেণি সংজ্ঞার মধ্যে স্থানীয় এবং গ্লোবালগুলির সমান ছিল।

  • run_path কেবল ফাইলগুলি চালিত করতে পারে না, তবে ডিম এবং ডিরেক্টরিগুলিও (বিশদগুলির জন্য এটির ডকুমেন্টেশনগুলি দেখুন)।


1
কোনও কারণে, এটি স্ক্রিনে প্রচুর তথ্য আউটপুট দেয় এটি মুদ্রণ করতে বলা হয়নি ( অ্যানাকোন্ডা পাইথন 3 এ ' বিল্টিনস ' ইত্যাদি)। এটিকে বন্ধ করার কোনও উপায় আছে যাতে মুদ্রণ () দিয়ে আউটপুট প্রাপ্ত তথ্যগুলিই কেবল রূপকল্পিত হয়?
জন ডন

বর্তমান ওয়ার্কস্পেসে সমস্ত ভেরিয়েবলগুলি সংরক্ষণের পরিবর্তে কী পাওয়া সম্ভব file_globals? এটি file_globals['...']প্রতিটি ভেরিয়েবলের জন্য টাইপ করে সংরক্ষণ করবে ।
অ্যাড্রায়ান

1
"তদুপরি, এক্সিকিউটড কোড দ্বারা নির্ধারিত কোনও ফাংশন এবং ক্লাসগুলি কোনও রান্পি ফাংশন ফিরে আসার পরে সঠিকভাবে কাজ করার গ্যারান্টিযুক্ত নয়" " আপনার ইউজ-কেসের উপর নির্ভর করে লক্ষণীয়
নোডাকাই

@ অ্যাড্রিয়ান এক্সিকিউট "গ্লোবাল ()। আপডেট (ফাইল_গ্লোবালস)"। ব্যক্তিগতভাবে আমার এই সমাধানটি সবচেয়ে ভাল লাগে কারণ বর্তমান ওয়ার্কস্পেসটি আপডেট করার সিদ্ধান্ত নেওয়ার আগে আমি সম্ভবত ত্রুটিগুলি ধরতে পারি।
রন কামিনস্কি

@ নোডাকাই তথ্যের জন্য ধন্যবাদ, আমি এটি মিস করেছি। এখনও কখনও এর মতো কোনও সমস্যা হয়নি, আমি অবাক হয়েছি যে এটি কীভাবে বন্ধ করে দেবে।
রন কামিনস্কি

21

এটি আরও ভাল, যেহেতু এটি কলার থেকে বিশ্বব্যাপী এবং স্থানীয়দের নেয়:

import sys
def execfile(filename, globals=None, locals=None):
    if globals is None:
        globals = sys._getframe(1).f_globals
    if locals is None:
        locals = sys._getframe(1).f_locals
    with open(filename, "r") as fh:
        exec(fh.read()+"\n", globals, locals)

আসলে, এটি পাই পাই 2 এর আরও কাছাকাছি execfile। পাইটসেট ব্যবহার করার সময় এটি আমার পক্ষে কাজ করেছিল যেখানে উপরে পোস্ট করা অন্যান্য সমাধান ব্যর্থ হয়েছে। ধন্যবাদ! :)
বোরিয়েল

17

আপনি আপনার নিজের ফাংশন লিখতে পারেন:

def xfile(afile, globalz=None, localz=None):
    with open(afile, "r") as fh:
        exec(fh.read(), globalz, localz)

আপনার যদি সত্যিই দরকার হয় ...


1
-1: এক্সিকিউট স্ট্যাটমেন্টটি এভাবে কাজ করে না। কোডটি পাইথনের কোনও সংস্করণে চলে না।
nosklo

6
-১: ডিফল্ট প্যারামিটার মানগুলি ফাংশন সংজ্ঞা সময়ে মূল্যায়ন করা হয়, উভয় তৈরি করে globalsএবং কলারের গ্লোবাল এবং স্থানীয় নেমস্পেসের পরিবর্তে localsসংজ্ঞা সম্বলিত মডিউলটির execfile()জন্য গ্লোবাল নেমস্পেসের দিকে নির্দেশ করে। সঠিক পন্থাটি হ'ল Noneডিফল্ট মান হিসাবে ব্যবহার করা এবং inspectমডিউলটির অন্তর্নির্ধারণের ক্ষমতাগুলির মাধ্যমে কলারের গ্লোবাল এবং স্থানীয়দের নির্ধারণ করা ।
সোভেন মারনাচ

12

আপনি যে স্ক্রিপ্টটি লোড করতে চান তা যদি আপনি চালিত যে একই ডিরেক্টরিতে থাকে, সম্ভবত "আমদানি" কাজটি করবে?

আপনি পরিবর্তনশীল আমদানি কোডে বিল্ট-ইন ফাংশন প্রয়োজন __ import__ এবং মডিউল বিচ্ছু এ খুঁজছেন মূল্য আছে।

>>> import sys
>>> sys.path = ['/path/to/script'] + sys.path
>>> __import__('test')
<module 'test' from '/path/to/script/test.pyc'>
>>> __import__('test').run()
'Hello world!'

test.py:

def run():
        return "Hello world!"

আপনি যদি পাইথন ৩.১ বা তার পরে ব্যবহার করছেন তবে আপনার আমদানিও একবার দেখে নেওয়া উচিত ।


এটি আমার জন্য সঠিক উত্তর ছিল। এই ব্লগটি importlib dev.to/0xcrypto/dynamic-importing-stuff-in-python--1805
নিক ব্র্যাডি

9

আমার যা ছিল তা এখানে ( fileউভয় উদাহরণে উত্স কোড সহ ফাইলের পথে ইতিমধ্যে বরাদ্দ করা হয়েছে):

execfile(file)

আমি এটি দিয়ে এটি প্রতিস্থাপন করেছি তা এখানে:

exec(compile(open(file).read(), file, 'exec'))

আমার প্রিয় অংশ: দ্বিতীয় সংস্করণটি পাইথন 2 এবং 3 উভয় ক্ষেত্রেই ঠিক সূক্ষ্মভাবে কাজ করে, যার অর্থ সংস্করণ নির্ভর যুক্তি যুক্ত করার প্রয়োজন নেই।


5

মনে রাখবেন যে আপনি যদি PEP-263 এনকোডিং ঘোষণাগুলি ascii বা utf-8 না ব্যবহার করেন তবে উপরের ধাঁচটি ব্যর্থ হবে। আপনাকে ডেটাটির এনকোডিং সন্ধান করতে হবে এবং কার্যকর করতে () এ হস্তান্তর করার আগে এটি সঠিকভাবে এনকোড করতে হবে।

class python3Execfile(object):
    def _get_file_encoding(self, filename):
        with open(filename, 'rb') as fp:
            try:
                return tokenize.detect_encoding(fp.readline)[0]
            except SyntaxError:
                return "utf-8"

    def my_execfile(filename):
        globals['__file__'] = filename
        with open(filename, 'r', encoding=self._get_file_encoding(filename)) as fp:
            contents = fp.read()
        if not contents.endswith("\n"):
            # http://bugs.python.org/issue10204
            contents += "\n"
        exec(contents, globals, globals)

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

খুব ভাল পয়েন্ট। এবং প্রদত্ত যে আমি এই উত্তরটি প্রায় ছয় মাস আগে লিখেছি, আমি ধরে নিলাম "উপরের ধরণ" দ্বারা আমি স্ট্যাকওভারফ্লো.com / a / 2849077 / 165082 (যা দুর্ভাগ্যক্রমে সমাধানের জন্য আপনাকে ক্লিক করতে হবে) বা নোমের উত্তর আরও ভাল:
এরিক

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

উত্তরের পোস্টারের নাম বাদ দিয়ে কোনও পোস্টে একটি নির্দিষ্ট "উত্তর" দিয়ে আপনি কীভাবে URL পাবেন?
দেবপ্লেয়ার

উত্সটি দেখুন এবং আইডি পান। উদাহরণস্বরূপ, আপনার প্রশ্নটি হবে স্ট্যাকওভারফ্লো . com/ প্রশ্নগুলি / 6৩6১৯৮ /।। আমি সবাই একটি আরও ভাল পদ্ধতির জন্য, তবে আমি যখন মন্তব্যটির কাছে ঘুরে দেখি তখন কিছুই দেখতে পাই না
এরিক

4

এছাড়াও, খাঁটি পাইথন সমাধান না হয়ে আপনি যদি আইপিথন ব্যবহার করেন (যেমন আপনার সম্ভবত যেমন হওয়া উচিত) তবে আপনি এটি করতে পারেন:

%run /path/to/filename.py

যা সমান সহজ।


1

আমি এখানে মাত্র একজন নবাগত তাই আমি যদি এটি পাই তবে এটি শুভ ভাগ্য:

কমান্ডটি দিয়ে >> অনুবাদক প্রম্পট >>> থেকে স্ক্রিপ্ট চালানোর চেষ্টা করার পরে

    execfile('filename.py')

যার জন্য আমি একটি "NameError: নাম 'execfile' সংজ্ঞায়িত করা হয় না" আমি খুব বেসিক চেষ্টা করেছি

    import filename

এটি ভাল কাজ করেছে :-)

আমি আশা করি এটি সহায়ক হতে পারে এবং আপনাকে ধন্যবাদ সবাইকে দারুণ ইঙ্গিত, উদাহরণ এবং সেই সমস্ত মাস্টারলি মন্তব্যযুক্ত কোডের টুকরোগুলির জন্য যারা নতুনদের জন্য দুর্দান্ত অনুপ্রেরণা!

আমি উবুন্টু 16.014 এলটিএস এক্স 64 ব্যবহার করি। পাইথন 3.5.3 (ডিফল্ট, নভেম্বর 17 2016, 17:05:23) [জিসিসি 5.4.0 20160609] লিনাক্সে


0

আমার কাছে, সবচেয়ে পরিষ্কার পন্থাটি হ'ল importlibপথটিকে মডিউল হিসাবে ফাইলটি ব্যবহার এবং আমদানি করা, যেমন:

from importlib import util

def load_file(name, path):
    spec = util.spec_from_file_location(name, path)
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module

ব্যবহারের উদাহরণ

আসুন একটি ফাইল আছে foo.py:

print('i got imported')
def hello():
    print('hello from foo')

এখন কেবল সাধারণ মডিউলের মতো এটি আমদানি করুন এবং ব্যবহার করুন:

>>> foo = load_file('foo', './foo.py')
i got imported
>>> foo.hello()
hello from foo

আমি এই কৌশলটি সরাসরি পদ্ধতির চেয়ে পছন্দ করি exec(open(...))কারণ এটি আপনার নামের স্থানগুলিকে বিশৃঙ্খলা করে না বা অহেতুক গণ্ডগোল করে না $PATH

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