سؤال

لدي خادم Python يعمل منذ فترة طويلة وأرغب في أن أتمكن من ترقية الخدمة دون إعادة تشغيل الخادم.ما هي أفضل طريقة للقيام بذلك؟

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()
هل كانت مفيدة؟

المحلول

يمكنك إعادة تحميل وحدة نمطية عندما يتم استيرادها بالفعل باستخدام الملف reload وظيفة مدمجة:

from importlib import reload  # Python 3.4+ only.
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

في بايثون 3، reload تم نقله إلى imp وحدة.في 3.4، imp تم إهماله لصالح importlib, ، و reload تمت إضافته إلى الأخير.عند استهداف الإصدار 3 أو إصدار أحدث، قم إما بالرجوع إلى الوحدة المناسبة عند الاتصال reload أو استيراده.

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

للاقتباس من المستندات:

يتم إعادة ترجمة كود وحدات Python و إعادة تنفيذ التعليمات البرمجية على مستوى الوحدة النمطية ، تحديد مجموعة جديدة من الكائنات التي مرتبطة بأسماء في الوحدة قاموس.وظيفة init ل لا تسمى وحدات التمديد أ المرة الثانية.كما هو الحال مع جميع الكائنات الأخرى في بايثون الكائنات القديمة هي فقط المستصلحة بعد التهم المرجعية انخفاض إلى الصفر.الأسماء في الوحدة يتم تحديث مساحة الاسم للإشارة إلى أي كائنات جديدة أو متغيرة.آخر مراجع إلى الكائنات القديمة (مثل الأسماء الخارجية للوحدة) ليست كذلك ارتداد للإشارة إلى الكائنات الجديدة ويجب تحديثها في كل مساحة اسم حيث تحدث إذا كان ذلك مطلوبا.

كما أشرت في سؤالك، سيتعين عليك إعادة البناء Foo الكائنات إذا Foo الطبقة تتواجد في foo وحدة.

نصائح أخرى

في بيثون 3،0-3،3 يمكنك استخدام: imp.reload(module)

BDFL له <لأ href = "HTTP: // mail.python.org/pipermail/edu-sig/2008-February/008421.html "يختلط =" noreferrer "> أجاب هذا السؤال.

ولكن، تم إهمال imp في 3.4، لصالح importlib (وذلك بفضل Stefan !).

أنا <م> التفكير ، لذلك، وكنت الآن استخدام <لأ href = "https://docs.python.org/dev/library/importlib.html#importlib.reload" يختلط = " noreferrer "> importlib.reload(module) ، على الرغم من أنني لست متأكدا.

ويمكن أن يكون من الصعب خصوصا لحذف وحدة نمطية إذا لم يكن بيثون النقي.

وهنا بعض المعلومات من: <لأ href = "http://web.archive.org/web/20080926094551/http://mail.python.org/pipermail/python-list/2003-December/241654. أتش تي أم أل "يختلط =" noreferrer "> كيف يمكنني حقا حذف وحدة المستوردة؟

<اقتباس فقرة>   

ويمكنك استخدام sys.getrefcount () لمعرفة العدد الفعلي لل   المراجع.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3
<اقتباس فقرة>   

وأرقام أكبر من 3 يشير إلى أن   سيكون من الصعب للتخلص من   وحدة. ونابعة من الداخل "فارغة"   (التي تحتوي على شيء) وحدة يجب أن يكون   القمامة التي تم جمعها بعد

>>> del sys.modules["empty"]
>>> del empty
<اقتباس فقرة>   

وكمرجع الثالثة هي قطعة أثرية   وظيفة getrefcount ().

وreload(module)، ولكن فقط اذا كان تماما قائمة بذاتها. إذا كان أي شيء آخر لديه إشارة إلى وحدة (أو أي كائن ينتمون إلى وحدة)، ثم ستحصل على أخطاء خفية وغريبة الناجمة عن القانون القديم التسكع أطول مما كنت متوقعا، وأشياء مثل isinstance لا تعمل عبر إصدارات مختلفة من نفس الرمز.

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

إذا كان لديك تبعيات دائرية، وهو أمر شائع جدا على سبيل المثال عندما كنت تتعامل مع إعادة تحميل الحزمة، يجب تفريغ جميع الوحدات في المجموعة دفعة واحدة. لا يمكنك أن تفعل هذا مع reload() لأنه سيتم إعادة استيراد كل وحدة قبل كانت تبعياته منتعشة، والسماح المراجع القديمة للتسلل إلى وحدات جديدة.

والطريقة الوحيدة للقيام بذلك في هذه الحالة هو الإختراق sys.modules، الذي هو نوع من غير معتمد. كنت عليك أن تذهب من خلال وحذف كل دخول sys.modules أردت إعادة تحميل على استيراد المقبل، وكذلك حذف إدخالات قيمها هي None للتعامل مع قضية تنفيذ علاقة مع التخزين المؤقت فشلت واردات النسبية. انها ليست لطيفة بشكل رهيب ولكن طالما لديك مجموعة كاملة بذاتها تبعيات الذي لا يترك المراجع خارج مصدر برنامج لها، وانها قابلة للتطبيق.

وانها على الارجح أفضل لإعادة تشغيل الملقم. : -)

if 'myModule' in sys.modules:  
    del sys.modules["myModule"]

لبايثون 2 استخدام دالة مضمنة في تحديث () :

reload(module)

لبايثون 2 و 3،2-3،3 استخدام تحميل من وحدة عفريت :

import imp
imp.reload(module)

ولكن imp تم إهمال منذ الإصدار 3.4 <لأ href = "HTTPS: //docs.python.org/3/library/importlib.html#importlib.reload "يختلط =" noreferrer "> في صالح importlib ، لذلك الاستخدام:

import importlib
importlib.reload(module)

أو

from importlib import reload
reload(module)

والتعليمة البرمجية التالية يسمح لك بيثون 2/3 التوافق:

try:
    reload
except NameError:
    # Python 3
    from imp import reload

ويمكنك استخدامه بمثابة reload() في كلا الإصدارين الأمر الذي يجعل الأمور أكثر بساطة.

والجواب المقبول لا يعالج من حالة X Y استيراد. هذا الرمز يعالج فإنه والحال استيراد القياسية أيضا:

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

في حالة إعادة شحن، ونحن إعادة تعيين أسماء المستوى الأعلى إلى القيم المخزنة في وحدة إعادة تحميل حديثا، الذي يعد استكمالا لها.

وهذه هي الطريقة الحديثة لإعادة وحدة نمطية:

from importlib import reload

إذا كنت ترغب في دعم إصدارات بيثون أقدم من 3.4، حاول هذا:

from sys import version_info
if version_info[0] < 3:
    pass # Python 2 has built in reload
elif version_info[0] == 3 and version_info[1] <= 4:
    from imp import reload # Python 3.0 - 3.4 
else:
    from importlib import reload # Python 3.5+

لاستخدامها، تشغيل reload(MODULE)، لتحل محل MODULE مع وحدة تريد إعادة تحميل.

وعلى سبيل المثال، reload(math) سيتم إعادة وحدة math.

إذا كنت كذلك لا في الخادم، ولكن النامية وتحتاج إلى إعادة تحميل الوحدة بشكل متكرر، إليك نصيحة لطيفة.

أولا، تأكد من أنك تستخدم ممتازة قذيفة IPython, ، من مشروع Jupyter Notebook.بعد تثبيت Jupyter، يمكنك البدء به ipython, ، أو jupyter console, ، أو حتى أفضل، jupyter qtconsole, ، والتي ستمنحك وحدة تحكم ملونة جميلة مع إكمال التعليمات البرمجية في أي نظام تشغيل.

الآن في الصدفة الخاصة بك، اكتب:

%load_ext autoreload
%autoreload 2

الآن، كل مرة قمت بتشغيل البرنامج النصي الخاص بك، سيتم إعادة تحميل الوحدات الخاصة بك.

ما وراء 2, ، هناك المزيد خيارات سحر التحميل التلقائي:

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.

لأمثالي الذين يريدون تفريغ جميع وحدات (عند تشغيل في مترجم بيثون تحت إيماكس ):

   for mod in sys.modules.values():
      reload(mod)

وعن المعلومات في وحدات إعادة شحن بيثون .

وEnthought الصفات على وحدة تعمل بشكل جيد لهذا الغرض. https://traits.readthedocs.org/en/4.3 0.0 / _modules / الصفات / UTIL / refresh.html

ووسوف تحميل أية وحدة نمطية التي تم تغيير وتحديث وحدات أخرى والأشياء وضح أن يتم استخدامه. أنها لا تعمل أكثر من مرة مع طرق __very_private__، ويمكن خنق على الميراث الصف، ولكنه يوفر لي مبالغ مجنونة من الوقت من الحاجة إلى إعادة تشغيل التطبيق المضيف عند كتابة باي كيوت اجهات، أو الأشياء التي تدير برامج داخلية مثل مايا أو الاسرائيلية المصرية في خطر . أنها لا تعمل ربما 20-30٪ من الوقت، لكنه ما زال لا يصدق مفيدة.

وحزمة Enthought للا إعادة تحميل الملفات لحظة تغيير - عليك أن نسميها explicitely - ولكن هذا لا ينبغي أن يكون كل ذلك من الصعب تنفيذ إذا كنت حقا في حاجة إليها

وأولئك الذين يستخدمون بيثون 3 وإعادة تحميل من importlib.

إذا كنت تعاني من مشاكل مثل ذلك يبدو أن وحدة لا إعادة تحميل ... هذا هو لأنه يحتاج إلى بعض الوقت لإعادة ترجمة PYC (تصل إلى 60 ثانية). أنا أكتب هذا التلميح فقط أن تعرف إذا واجهت هذا النوع من المشكلة.

2018-02-01

  1. وحدة foo يجب أن يتم استيرادها بنجاح مقدما.
  2. from importlib import reload, reload(foo)

31.5.importlib - تنفيذ الاستيراد - وثائق Python 3.6.4

خيار آخر.انظر أن بايثون الافتراضي importlib.reload سيتم فقط إعادة استيراد المكتبة التي تم تمريرها كوسيطة.هو - هي متعود أعد تحميل المكتبات التي يستوردها lib الخاص بك.إذا قمت بتغيير الكثير من الملفات ولديك حزمة معقدة إلى حد ما لاستيرادها، فيجب عليك القيام بذلك إعادة تحميل عميق.

اذا كنت تمتلك IPython أو كوكب المشتري بعد تثبيته، يمكنك استخدام وظيفة لإعادة تحميل جميع libs بعمق:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

إذا لم يكن لديك Jupyter، فقم بتثبيته باستخدام هذا الأمر في الصدفة الخاصة بك:

pip3 install jupyter

وبالنسبة لي لحالة ABAQUS هو الطريقة التي يعمل بها. تخيل الملف الخاص بك هو Class_VerticesEdges.py

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])

وهناك طريقة أخرى يمكن أن يكون لاستيراد وحدة في وظيفة. بهذه الطريقة عند اكتمال وظيفة وحدة يحصل القمامة التي تم جمعها.

وحصلت على الكثير من المتاعب في محاولة لإعادة تحميل شيء داخل النص سامية، ولكن في النهاية أنا قد كتبت هذه الأداة المساعدة لإعادة وحدات على نص سامية بناء على sublime_plugin.py كود يستخدم لإعادة تحميل وحدات.

وهذا أدناه يقبل منك إعادة تحميل وحدات من مسارات مع المساحات على أسمائهم، ثم في وقت لاحق بعد إعادة يمكنك استيراد تماما كما تفعل عادة.

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __name__ == "__main__":
    run_tests()

إذا قمت بتشغيل لأول مرة، وهذا ينبغي أن تحمل الوحدة، ولكن إذا كان لاحقا يمكنك مرة أخرى run_tests() طريقة / وظيفة فإنه سيتم إعادة الاختبارات الملفات. مع نص سامية (Python 3.3.6) هذا يحدث كثيرا لأن المفسر لم يغلق (إلا إذا كنت أعد النص سامية، أي مترجم Python3.3).

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