2015-04-23 4 views
3

Мне нужно объединить два текстовых файла вместе и создать из него новый список. Первый содержит URL-адреса и другие urlpaths/folder, которые должны применяться к каждому URL-адресу. Im Работа со списками, и это очень медленно, потому что его грубо около 200 000 предметов.Список Python Append Slow?

Пример:

urls.txt:

http://wwww.google.com 
.... 

paths.txt:

/abc 
/bce 
.... 

Позже, после того, как цикл закончен, должен быть новый список с

http://wwww.google.com/abc 
http://wwww.google.com/bce 

Код Python :

URLS_TO_CHECK = [] #defined as global, needed later 

def generate_list(): 
    urls = open("urls.txt", "r").read().splitlines() 
    paths = open("paths.txt", "r").read().splitlines() 
    done = open("done.txt", "r").read().splitlines() #old done urls 

    for i in range(len(urls)): 
    for x in range(len(paths)): 
     url = re.search('(http://(.+?)....)', urls[i]) #needed 
     url = "%s%s" %(url.group(1), paths[x]) 
     if url not in URLS_TO_CHECK: 
      if url not in done: 
       URLS_TO_CHECK.append(url) ##<<< slow! 

Уже прочитал некоторые другие темы, о map функции, отключить gc, но не может использовать map функции с моей программой. и отключить gc действительно не помогло.

+1

Попробуйте изменить URLS_TO_CHECK к набору() вместо этого, пока упорядочение не имеет значения для вас. – Ben

+0

Вы также можете сделать 'done' набор, который ускорит тест членства. Прошли ли какие-либо профилирования? – jonrsharpe

+2

У вас даже «профиль» ваш код? Вы создаете множество списков ('range (len (url)) и т. Д.), Читайте все файлы в памяти вместо их итерации по ним, и, честно говоря, я думаю, что« append »здесь не является узким местом. –

ответ

1

Этот подход имеет преимущество такие как:

  • быстрый поиск в наборе - O (1) вместо O (n)
  • генерация значений по требованию, а не строить весь список, как однажды
  • чтения из файла в кусках вместо загрузки целых данных сразу
  • избежать ненужных регулярных выражений

def yield_urls(): 
    with open("paths.txt") as f: 
     paths = f.readlines() # needed in each iteration and iterates over, may be list 

    with open("done.txt") as f: 
     done_urls = set(f.readlines()) # needed in each iteration and looked up, set is O(1) vs O(n) in list 

    # resources are cleaned up after with 

    with open("urls.txt", "r") as f: 
     for url in f: # iterate over list, not big list of ints generated before iteratiob, much quicker 
      for subpath in paths: 
       full_url = ''.join((url[7:], subpath)) # no regex means faster, maybe string formatting is quicker than join, you need to check 
       # also, take care about trailing newlines in strings read from file 
       if full_url not in done_urls: # fast lookup in set 
        yield full_url # yield instead of appending 

# usage 
for url in yield_urls(): 
    pass # to something with url 
+0

Не называть' readlines', если вам не нужен его аргумент - просто используйте 'list (f)' и 'set (f) 'вместо этого. Вы также используете '. '.join', где вы должны просто использовать' + ':' url [7:] + subpath'. – Veedrac

0
URLS_TO_CHECK = set(re.findall("'http://(.+?)....'",open("urls.txt", "r").read())) 
for url in URLS_TO_CHECK: 
    for path in paths: 
     check_url(url+path) 

, вероятно, будет намного быстрее ... и я думаю, что его по существу то же самое ....

+0

Это не то же самое? –

+0

Не могу сделать это, потому что мне нужно добавить пути (from paths.txt) к каждому URL-адресу в urls.txt. – matwet

0

Поиск в словарях быстрее по сравнению списки Python: List vs Dict for look up table

URLS_TO_CHECK = {} #defined as global, needed later 

def generate_list(): 
    urls = open("urls.txt", "r").read().splitlines() 
    paths = open("paths.txt", "r").read().splitlines() 
    done = dict([(l, True) for l in open("done.txt", "r").read().splitlines()]) #old done urls 

    for i in range(len(urls)): 
    for x in range(len(paths)): 
     url = re.search('(http://(.+?)....)', urls[i]) #needed 
     url = "%s%s" %(url.group(1), paths[x]) 
     if not url in URLS_TO_CHECK: 
     if not url in done: 
      URLS_TO_CHECK[url] = True #Result in URLS_TO_CHECK.keys() 
+0

'urls = open (" urls.txt "," r "). Read(). Splitlines()' и 'paths = open (" paths.txt "," r "). Read().splitlines() 'использование избыточной памяти использования лучше использовать итератор –

+0

, если размер памяти не является проблемой. Можете также оставить –

Смежные вопросы