2009-03-31 19 views
16

सबसे अच्छा तरीका है पायथन में एक निर्देशिका से एक यादृच्छिक फ़ाइल चुनने के लिए क्या है से एक यादृच्छिक फ़ाइल चुनने के लिए?सबसे अच्छा तरीका है एक निर्देशिका

संपादित करें: यहाँ मैं क्या कर रहा हूँ है:

import os 
import random 
import dircache 

dir = 'some/directory' 
filename = random.choice(dircache.listdir(dir)) 
path = os.path.join(dir, filename) 

यह विशेष रूप से बुरा है, या वहाँ एक विशेष रूप से बेहतर तरीका है?

+0

क्षमा दोस्तों, मैं गलती से इससे पहले कि मैं मेरे सवाल में प्रवेश समाप्त प्रस्तुत की। हालांकि बहुत कुछ नहीं बदला जाना चाहिए। – JasonSmith

+0

क्या आप दौड़-स्थिति समस्या को स्पष्ट कर सकते हैं? मुझे लगता है कि आप किसी फ़ाइल को चुनने और खोलने का मतलब नहीं लेते हैं (जब कोई इसे उदाहरण के लिए खोलने और खोलने की कोशिश करने के बीच इसे हटा सकता है), लेकिन यह स्पष्ट रूप से यह कहने लायक हो सकता है (मान लीजिए कि मैं आपको सही तरीके से व्याख्या कर रहा हूं)। – Brian

+0

दौड़ की स्थिति है क्योंकि कई प्रक्रियाएं एक साथ ऐसा कर रही हैं? या दौड़ की स्थिति तब होगी जब एक लेखक फाइलें बना रहा है और यह पाठक जो उन्हें चुन रहा है? –

उत्तर

39
import os, random 
random.choice(os.listdir("C:\\")) #change dir name to whatever 

आपकी संपादित सवाल के बारे में कर रहे हैं: पहला, मैं एक ssume आपको dircache का उपयोग करने के जोखिम के साथ-साथ यह तथ्य भी है कि यह deprecated since 2.6, and removed in 3.0 है।

सभी का दूसरा, मैं देख नहीं है जहां किसी भी जाति हालत यहां मौजूद है। आपकी dircache ऑब्जेक्ट मूल रूप से अपरिवर्तनीय है (निर्देशिका सूची कैश्ड होने के बाद, इसे फिर कभी नहीं पढ़ा जाता है), इसलिए इसमें समवर्ती पढ़ने में कोई नुकसान नहीं होता है।

उसके अलावा, मुझे समझ नहीं आता क्यों आप इस समाधान के साथ किसी भी समस्या दिख रहा है। बस ठीक है।

+1

उल्लेख करने के लिए धन्यवाद कि डायरकेच को बहिष्कृत किया गया है। –

1

इस्तेमाल की जाने वाली भाषा से स्वतंत्र, आप एक निर्देशिका में फ़ाइलों के सभी संदर्भों को एक सरणी (जैसे 'listFiles') जैसे डेटास्ट्रक्चर में पढ़ सकते हैं, सरणी की लंबाई प्राप्त करें। '0' से 'arrayLength-1' की श्रेणी में यादृच्छिक संख्या की गणना करें और फ़ाइल को निश्चित अनुक्रमणिका पर एक्सेस करें। यह न केवल पायथन में काम करना चाहिए।

1

यदि आप हाथ से पहले नहीं जानते हैं कि कौन सी फाइलें हैं, तो आपको एक सूची प्राप्त करने की आवश्यकता होगी, फिर सूची में एक यादृच्छिक अनुक्रमणिका चुनें।

import os 
import random 

def getRandomFile(path): 
    """ 
    Returns a random filename, chosen among the files of the given path. 
    """ 
    files = os.listdir(path) 
    index = random.randrange(0, len(files)) 
    return files[index] 

संपादित:

यहाँ एक प्रयास है सवाल अब एक "रेस स्थिति" है, जो मैं केवल यह मान सकते हैं फ़ाइलों की विशिष्ट समस्या जोड़ा जा रहा है/हटा दिया है, जबकि आप कर रहे हैं का डर का उल्लेख है एक यादृच्छिक फ़ाइल लेने की कोशिश की प्रक्रिया में।

मुझे विश्वास नहीं है कि इसके आस-पास एक रास्ता है, यह ध्यान में रखते हुए कि कोई I/O ऑपरेशन स्वाभाविक रूप से "असुरक्षित" है, यानी यह असफल हो सकता है। तो, एल्गोरिथ्म एक दिया निर्देशिका में अनियमित रूप से चुने फ़ाइल खोलने के लिए चाहिए:

  • असल open() फ़ाइल का चयन किया है, और एक विफलता संभाल, के बाद से फ़ाइल अब वहां नहीं
  • हो सकता है शायद एक सेट के लिए खुद को सीमित कोशिश करता की संख्या, तो यह अगर निर्देशिका खाली है या मरता नहीं है फ़ाइलों में से कोई भी पठनीय
+0

हाँ, इसके बारे में नहीं पता था, हालांकि इसे किसी अन्य जवाब में देखा। जानना अच्छा है, धन्यवाद! – unwind

4

भाषा नास्तिक समाधान:

1) कुल प्राप्त करें। निर्दिष्ट निर्देशिका में फ़ाइलों का।

2) [कुल 0 से एक यादृच्छिक संख्या चुनें। फाइलों - 1]।

3) उपयुक्त नामांकित संग्रह या ऐसे के रूप में फ़ाइल नामों की सूची प्राप्त करें।

4) n वें तत्व है, जहां n यादृच्छिक संख्या है उठाओ।

4

यदि आप निर्देशिकाएं चाहते हैं, तो युवाल ए का जवाब। अन्यथा:

import os, random 

random.choice([x for x in os.listdir("C:\\") if os.path.isfile(os.path.join("C:\\", x))]) 
2

दिया आप स्मृति में अपने सभी इनपुट लोड कर रहा है समाधान, जो बड़े आदानों/पदानुक्रम के लिए एक समस्या बन सकती से अधिकांश के साथ समस्या। टॉम क्रिस्सेन और नेट टॉर्किंगटन द्वारा The Perl Cookbook से अनुकूलित समाधान यहां दिया गया है। एक निर्देशिका के नीचे कहीं भी एक यादृच्छिक फ़ाइल पाने के लिए:

#! /usr/bin/env python 
import os, random 
n=0 
random.seed(); 
for root, dirs, files in os.walk('/tmp/foo'): 
    for name in files: 
    n=n+1 
    if random.uniform(0, n) < 1: rfile=os.path.join(root, name) 
print rfile 

थोड़ा सामान्यीकरण एक आसान स्क्रिप्ट बनाता है:

$ cat /tmp/randy.py 
#! /usr/bin/env python 
import sys, random 
random.seed() 
n=1 
for line in sys.stdin: 
    if random.uniform(0, n)<1: rline=line 
    n=n+1 
sys.stdout.write(rline) 

$ /tmp/randy.py < /usr/share/dict/words 
chrysochlore 

$ find /tmp/foo -type f | /tmp/randy.py 
/tmp/foo/bar 
संबंधित मुद्दे