سؤال

وضع التالي في ملف hello.pyeasy_install paramiko إذا لم تكن قد حصلت عليه):

hostname,username,password='fill','these','in'
import paramiko
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(hostname=hostname, username=username, password=password)
i,o,e = c.exec_command('ls /')
print(o.read())
c.close()

ملء في السطر الأول بشكل مناسب.

الآن اكتب

python hello.py

وسترى بعض هل الانتاج.

الآن بدلا نوع

python

ثم من خلال مترجم نوع

import hello

وفويلا!توقف!وسوف unhang إذا كنت التفاف التعليمات البرمجية في الدالة foo والقيام import hello; hello.foo() بدلا من ذلك.

لماذا Paramiko تعليق عند استخدامها داخل وحدة التهيئة? كيف Paramiko حتى علم أنه يجري استخدامها من خلال وحدة التهيئة في المقام الأول ؟

هل كانت مفيدة؟

المحلول

Paramiko يستخدم منفصلة المواضيع الأساسية للنقل.يجب أن أبدا لديك وحدة الذي يولد موضوع كأثر جانبي المستوردة.كما أفهم أن هناك واحد استيراد قفل المتاحة ، حتى عندما يكون الطفل موضوع من وحدة محاولات أخرى الاستيراد ، فإنه يمكن منع إلى أجل غير مسمى ، لأن الترابط الرئيسي لا يزال يحمل القفل.(ربما يكون هناك البعض gotchas أنني لست على علم أيضا)

في عام ، وحدات يجب أن لا يكون لها آثار جانبية من أي نوع عند استيراد أو وأنت تسير في الحصول على نتائج غير متوقعة.مجرد عقد التنفيذ مع __name__ == '__main__' خدعة ، وسوف يكون على ما يرام.

[عدل] أنا لا يمكن أن يبدو لخلق اختبار بسيط القضية أن يستنسخ هذا الجمود.أنا لا تزال تحمل إنها خيوط القضية مع استيراد, لأن الرمز هو انتظار الحدث الذي لم الحرائق.قد يكون هذا الخلل في paramiko ، أو الثعبان, ولكن الخبر السار هو أنه يجب أن لا نرى أي وقت مضى إذا كنت تفعل الأشياء بشكل صحيح ;)

هذا هو مثال جيد لماذا تريد دائما إلى تقليل الآثار الجانبية, و لماذا تقنيات البرمجة الوظيفية أصبحت أكثر انتشارا.

نصائح أخرى

كما JimB وأشار إلى أنه هو قضية استيراد عندما الثعبان يحاول ضمنيا استيراد str.decode('utf-8') فك عند "الاستخدام الأول" خلال اتصال ssh محاولة.انظر تحليل القسم للحصول على التفاصيل.

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

  1. سهلة و عاقل - إصلاح المشكلة - كما سبق ذكره - هو وضع الكود الخاص بك في if __name__ == '__main__': الجسم الذي سوف يعدم إذا قمت بتنفيذ هذا وحدة نمطية محددة و لن يعدم عند هذا mmodule يتم استيرادها من قبل وحدات أخرى.

  2. (لا ينصح به) آخر الإصلاح لا مجرد دمية str.فك('utf-8') في التعليمات البرمجية الخاصة بك قبل الاتصال SSHClient.connect() - انظر التحليل أدناه.

ما السبب في هذه المشكلة ؟

تحليل (كلمة مرور بسيطة المصادقة)

تلميح:إذا كنت ترغب في تصحيح خيوط في بيثون استيراد مجموعة threading._VERBOSE = True

  1. paramiko.SSHClient().connect(.., look_for_keys=False, ..) ضمنا يولد موضوع جديد للاتصال الخاص بك.يمكنك أن ترى أيضا هذا إذا كنت بدوره على التصحيح الناتج عن paramiko.transport.

[Thread-5 ] [paramiko.transport ] DEBUG : starting thread (client mode): 0x317f1d0L

  1. ويتم ذلك أساسا كجزء من SSHClient.connect().عندما client.py:324::start_client() يسمى قفل يتم إنشاؤه transport.py:399::event=threading.Event() و الموضوع بدأ transport.py:400::self.start().علما بأن start() وطريقة ثم تنفيذ الفئة transport.py:1565::run() الأسلوب.

  2. transport.py:1580::self._log(..) طباعة سجل لدينا رسالة "بدء تشغيل مؤشر ترابط" ثم ينتقل إلى transport.py:1584::self._check_banner().

  3. check_banner لا شيء واحد.فإنه يسترد ssh راية (أول استجابة من ملقم) transport.py:1707::self.packetizer.readline(timeout) (علما بأن مهلة فقط مأخذ قراءة مهلة), التحقق من آلية في النهاية وإلا مرات.

  4. في حالة الخادم راية وردت ، فإنه يحاول utf-8 فك شفرة الاستجابة سلسلة packet.py:287::return u(buf) و thats حيث الجمود يحدث.على u(s, encoding='utf-8') لا str.فك('utf-i') و ضمنا الواردات encodings.utf8 في encodings:99 عبر encodings.search_function تنتهي في استيراد الجمود.

لذا القذرة الإصلاح سيكون مجرد استيراد utf-8 فك مرة واحدة لكي لا كتلة على أن تحديد الاستيراد بسبب وحدة استيراد sideeffects.(''.decode('utf-8'))

Fix

القذرة إصلاح - لا ينصح

import paramiko
hostname,username,password='fill','these','in'
''.decode('utf-8')  # dirty fix
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(hostname=hostname, username=username, password=password)
i,o,e = c.exec_command('ls /')
print(o.read())
c.close()

إصلاح جيد

import paramiko
if __name__ == '__main__':
    hostname,username,password='fill','these','in'
    c = paramiko.SSHClient()
    c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    c.connect(hostname=hostname, username=username, password=password)
    i,o,e = c.exec_command('ls /')
    print(o.read())
    c.close()

المرجع paramiko تعقب المسألة:مسألة 104

"".فك("utf-8") لم يكن العمل بالنسبة لي لقد انتهى به هذا.

from paramiko import py3compat
# dirty hack to fix threading import lock (issue 104) by preloading module
py3compat.u("dirty hack")

لدي المجمع paramiko مع أن تنفذ.https://github.com/bucknerns/sshaolin

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