لماذا يتم تعليق كود بايثون هذا عند الاستيراد/الترجمة ولكنه يعمل في الغلاف؟
-
06-07-2019 - |
سؤال
أحاول استخدام لغة بايثون لنقل ملف sftp، ويعمل الكود بشكل رائع في الغلاف التفاعلي - حتى أنه يتم لصقه مرة واحدة.
عندما أحاول استيراد الملف (فقط لتجميعه)، يتم تعليق التعليمات البرمجية دون أي استثناءات أو أخطاء واضحة.
كيف يمكنني تجميع الكود، أو هل لدى شخص ما كود عمل ينجز sftp بطريقة أخرى؟
يتم تعليق هذا الرمز مباشرةً عند عبارة ssh.connect():
""" ProblemDemo.py Chopped down from the paramiko demo file. This code works in the shell but hangs when I try to import it! """ from time import sleep import os import paramiko sOutputFilename = "redacted.htm" #-- The payload file hostname = "redacted.com" ####-- WARNING! Embedded passwords! Remove ASAP. sUsername = "redacted" sPassword = "redacted" sTargetDir = "redacted" #-- Get host key, if we know one. hostkeytype = None hostkey = None host_keys = {} try: host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts')) except IOError: try: # try ~/ssh/ too, because windows can't have a folder named ~/.ssh/ host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/ssh/known_hosts')) except IOError: print '*** Unable to open host keys file' host_keys = {} if host_keys.has_key(hostname): hostkeytype = host_keys[hostname].keys()[0] hostkey = host_keys[hostname][hostkeytype] print 'Using host key of type %s' % hostkeytype ssh = paramiko.Transport((hostname, 22)) ssh.connect(username=sUsername, password=sPassword, hostkey=hostkey) sftp = paramiko.SFTPClient.from_transport(ssh) sftp.chdir (sTargetDir) sftp.put (sOutputFilename, sOutputFilename) ssh.close()
المحلول 3
وغرابة جانبا، كنت فقط باستخدام استيراد ترجمة التعليمات البرمجية. تحويل النص إلى وظيفة يبدو وكأنه تعقيد لا لزوم لها لهذا النوع من التطبيق.
وتم البحث عن وسائل بديلة لتجميع وجدت:
import py_compile py_compile.compile("ProblemDemo.py")
ولقد تولد عن هذا الملف PYC التي تعمل على النحو المنشود. لذا فإن الدرس المستفاد هو أن استيراد ليست وسيلة قوية لتجميع مخطوطات الثعبان.
نصائح أخرى
وهذا هو في الواقع فكرة سيئة لتنفيذ هذا النوع من التعليمات البرمجية في وقت الاستيراد، على الرغم من أنني لست متأكدا من السبب في ذلك توقف - قد يكون من أن آلية استيراد يفعل شيئا غريبا التي تتفاعل بشدة مع paramiko (القضايا المتعلقة موضوع ربما؟). على أي حال، فإن الحل المعتاد هو لتنفيذ وظيفة إلى وظيفة:
def my_expensive_function(args):
pass
if __name__ == '__main__':
import sys
my_expensive_functions(sys.args)
وبهذه الطريقة، فقط استيراد وحدة لن تفعل أي شيء، ولكن تشغيل البرنامج النصي سيتم تنفيذ وظيفة مع الحجج المقدمة في سطر الأوامر.
قد لا يكون هذا سببًا مباشرًا، ولكن نادرا ما تفعل ذلك من أي وقت مضى تريد تنفيذ "الوظيفة" عند الاستيراد.عادة يجب عليك تحديد أ فصل أو وظيفة التي تتصل بها بعد ذلك مثل هذا:
import mymodule
mymodule.run()
عادةً ما يجب أن يقتصر الكود "العام" الذي تقوم بتشغيله في عملية الاستيراد على عمليات الاستيراد وتعريفات المتغيرات وتعريفات الوظائف والفئة وما شابه ذلك...