سؤال

لديّ جزء من التعليمات البرمجية التي أستخدمها للبحث عن المنافسات التنفيذية لملفات اللعبة وإرجاع الدلائل. أرغب حقًا في الحصول على مؤشر من نوع التقدم حول المدى الذي يبعد os.walk هو. كيف يمكنني إنجاز مثل هذا الشيء؟

حاولت القيام startpt = root.count(os.sep) وقياس ذلك ولكن هذا يعطي مدى عمق os.walk في شجرة الدليل.

def locate(filelist, root=os.curdir): #Find a list of files, return directories.
    for path, dirs, files in os.walk(os.path.abspath(root)):
        for filename in returnMatches(filelist, [k.lower() for k in files]):
            yield path + "\\"
هل كانت مفيدة؟

المحلول 3

لقد اكتشفت هذا.

لقد استخدمت OS.Listdir للحصول على قائمة بأدلة Toplevel ، ثم استخدمت وظيفة .split على المسار الذي عاده OS.Walk ، مع إرجاع دليل المستوى الأول الذي كان موجودًا حاليًا.

لقد تركني ذلك مع قائمة من الدلائل Toplevel ، والتي يمكنني العثور عليها في فهرس الدليل الحالي لـ OS.Walk ، وقارن الفهرس الذي تم إرجاعه بطول القائمة ، مما يمنحني ٪ مكتملًا. ؛)

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

هنا هو الرمز النهائي من الحصول على تقدمي:

def locateGameDirs(filelist, root=os.curdir): #Find a list of files, return directories.
    toplevel = [folder for folder in os.listdir(root) if os.path.isdir(os.path.join(root, folder))] #List of top-level directories
    fileset = set(filelist)

    for path, dirs, files in os.walk(os.path.abspath(root)):

        curdir = path.split('\\')[1] #The directory os.walk is currently in.

        try: #Thrown here because there's a nonexistant(?) first entry.
            youarehere = toplevel.index(curdir)
            progress = int(((youarehere)/len(toplevel))*100)
        except:
            pass

        for filename in returnMatches(filelist, [k.lower() for k in files]):
            yield filename, path + "\\", progress

والآن لأغراض تصحيح الأخطاء ، أقوم بذلك بشكل أكبر في الكود:

    for wow in locateGameDirs(["wow.exe", "firefox.exe", "vlc.exe"], "C:\\"):
    print wow

هل هناك طريقة صغيرة لطيفة للتخلص من تلك المحاولة/ما عدا؟ يبدو أن التكرار الأول للمسار لا يعطيني شيئًا ...

نصائح أخرى

هذا يعتمد!

إذا تم توزيع الملفات والأدلة بشكل أو بآخر ، فيمكنك إظهار عملية تقريبية من خلال افتراض أن كل دليل toplevel سيستغرق نفس الوقت. ولكن إذا لم يتم توزيعها بالتساوي ، فلن تتمكن من معرفة ذلك بثمن بخس. يجب عليك إما أن تعرف تقريبًا مدى ملاءمة كل دليل مقدمًا ، أو عليك أن تقوم بالتواصل.

هذا هو: قل أن لديك 4 أدلة toplevel ، وكل واحد يحتوي على 4 ملفات. إذا افترضت أن كل DIR Toplevel يحصل على 25 ٪ من التقدم ، ويأخذ كل ملف 25 ٪ أخرى من التقدم لهذا DIR ، يمكنك إظهار مؤشر تقدم لطيف. ولكن إذا تبين أن آخر subdir احتواء العديد من الملفات أكثر من أول مؤشر التقدم الخاص بك ، فسيصل إلى 75 ٪ قبل معرفة ذلك. لا يمكنك حقًا إصلاح أنه إذا كان OS.Walk نفسه هو عنق الزجاجة (وليس معالجتك) وهي شجرة دليل تعسفي (لا تعرف مسبقًا تقريبًا كم من الوقت ستستغرق كل شجرة فرعية).

وبالطبع هذا يفترض أن التكلفة هنا هي نفسها عن كل ملف ...

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

قم بذلك في ممرين: قم أولاً بإحصاء عدد الملفات/المجلدات الكلية الموجودة في الشجرة ، ثم أثناء التمريرة الثانية ، تقوم بمعالجة فعلية.

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

len(list(os.walk(os.path.abspath(root))))

لكن هذا سيستغرق بعض الوقت وربما تحتاج إلى مؤشر تقدم لذلك ...

للعثور على عدد الملفات بسرعة ، ستحتاج إلى نظام ملفات يتتبع عدد الملفات لك.

ربما يمكنك حفظ المجموع من المدى السابق واستخدام ذلك كتقدير

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

على Windows ، انظر كل شىء. على UNIX ، تحقق من موقع. لست متأكدًا من Mac ، لكنني متأكد من أن هناك خيارًا أيضًا.

كما قلت في التعليق ، من المحتمل أن تقع رقبة زجاجة الأداء خارج locate وظيفة. لك returnMatches هي وظيفة باهظة الثمن إلى حد ما. أعتقد أنك ستكون أفضل حالًا في استبداله بالرمز التالي:

def locate(filelist, root=os.curdir)
    fileset = set(filelist)            # if possible, pass the set instead of the list as a first argument
    for path, dirs, files in os.walk(os.path.abspath(root)):
            if any(file.lower() in fileset for file in files):
                yield path + '\\'

وبهذه الطريقة ، تقلل من عدد العمليات المهبطة ، وتسفر مرة واحدة لكل ملف في الدليل (وهو ما أعتقد أنه ما قمت به بالفعل) ويمكنك أن تنسى التقدم في نفس الوقت. لا أعتقد أن التقدم سيكون ميزة متوقعة للواجهة على أي حال.

التفكير خارج الصندوق هنا ... ماذا لو فعلت ذلك بناءً على بحجم:

  • يستخدم عملية فرعية لتشغيل "du -sb" والحصول على total_size من دليل الجذر الخاص بك
  • أثناء المشي ، تحقق من حجم كل ملف وانخفاض من Total_size (يمنحك المتبقية)
  • PCT_COMPLETE = (TOTAL_SIZE - المتبقي _size)/Total_size

أفكار؟

-جاج

أحد التحسينات التي يمكنك القيام بها - أنت تقوم بتحويل Filelist إلى مجموعة على كل مكالمة لإرجاعها ، على الرغم من أنها لا تتغير أبدًا. انقل التحويل إلى بداية وظيفة "تحديد موقع" وقم بتمرير المجموعة على كل التكرار.

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

import os, sys, time

def calc_progress(progress, root, dirs):
    prog_start, prog_end, prog_slice = 0.0, 1.0, 1.0

    current_progress = 0.0
    parent_path, current_name = os.path.split(root)
    data = progress.get(parent_path)
    if data:
        prog_start, prog_end, subdirs = data
        i = subdirs.index(current_name)
        prog_slice = (prog_end - prog_start) / len(subdirs)
        current_progress = prog_slice * i + prog_start

        if i == (len(subdirs) - 1):
            del progress[parent_path]

    if dirs:
        progress[root] = (current_progress, current_progress+prog_slice, dirs)

    return current_progress

def walk(start_root):
    progress = {}
    print 'Starting with {start_root}'.format(**locals())

    for root, dirs, files in os.walk(start_root):
        print '{0}: {1:%}'.format(root[len(start_root)+1:], calc_progress(progress, root, dirs))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top