لماذا Paramiko تعليق إذا كنت تستخدم أثناء تحميل وحدة ؟
-
22-07-2019 - |
سؤال
وضع التالي في ملف hello.py (و easy_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 محاولة.انظر تحليل القسم للحصول على التفاصيل.
في عام واحد لا أستطيع أن أؤكد بما فيه الكفاية التي يجب تجنب وجود وحدة تلقائيا التفريخ مواضيع جديدة على الاستيراد.إذا كنت تستطيع ، في محاولة لتجنب السحر الوحدة البرمجية بشكل عام كما انها دائما تقريبا يؤدي إلى الآثار الجانبية غير المرغوب فيها.
سهلة و عاقل - إصلاح المشكلة - كما سبق ذكره - هو وضع الكود الخاص بك في
if __name__ == '__main__':
الجسم الذي سوف يعدم إذا قمت بتنفيذ هذا وحدة نمطية محددة و لن يعدم عند هذا mmodule يتم استيرادها من قبل وحدات أخرى.(لا ينصح به) آخر الإصلاح لا مجرد دمية str.فك('utf-8') في التعليمات البرمجية الخاصة بك قبل الاتصال
SSHClient.connect()
- انظر التحليل أدناه.
ما السبب في هذه المشكلة ؟
تحليل (كلمة مرور بسيطة المصادقة)
تلميح:إذا كنت ترغب في تصحيح خيوط في بيثون استيراد مجموعة threading._VERBOSE = True
paramiko.SSHClient().connect(.., look_for_keys=False, ..)
ضمنا يولد موضوع جديد للاتصال الخاص بك.يمكنك أن ترى أيضا هذا إذا كنت بدوره على التصحيح الناتج عنparamiko.transport
.
[Thread-5 ] [paramiko.transport ] DEBUG : starting thread (client mode): 0x317f1d0L
ويتم ذلك أساسا كجزء من
SSHClient.connect()
.عندماclient.py:324::start_client()
يسمى قفل يتم إنشاؤهtransport.py:399::event=threading.Event()
و الموضوع بدأtransport.py:400::self.start()
.علما بأنstart()
وطريقة ثم تنفيذ الفئةtransport.py:1565::run()
الأسلوب.transport.py:1580::self._log(..)
طباعة سجل لدينا رسالة "بدء تشغيل مؤشر ترابط" ثم ينتقل إلىtransport.py:1584::self._check_banner()
.check_banner
لا شيء واحد.فإنه يسترد ssh راية (أول استجابة من ملقم)transport.py:1707::self.packetizer.readline(timeout)
(علما بأن مهلة فقط مأخذ قراءة مهلة), التحقق من آلية في النهاية وإلا مرات.في حالة الخادم راية وردت ، فإنه يحاول 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()
"".فك("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