Является ли Python os.path.join медленным? - PullRequest
2 голосов
/ 12 января 2011

Мне сказали, что os.path.join ужасно медленный в питоне, и я должен вместо этого использовать конкатенацию строк ('%s/%s' % (x, y)).Есть ли такая большая разница, и если да, то как я могу ее отследить?

Ответы [ 7 ]

12 голосов
/ 12 января 2011
$ python -mtimeit -s 'import os.path' 'os.path.join("/root", "file")'
1000000 loops, best of 3: 1.02 usec per loop
$ python -mtimeit '"/root" + "file"'
10000000 loops, best of 3: 0.0223 usec per loop

Так что да, это почти в 50 раз медленнее. Тем не менее, 1 микросекунда все еще ничего , поэтому я не буду учитывать разницу. Используйте os.path.join: она кроссплатформенная, более читаемая и менее подвержена ошибкам.

РЕДАКТИРОВАТЬ: Два человека уже прокомментировали, что import объясняет разницу. Это не так, поскольку -s является флагом установки, поэтому import не учитывается в сообщаемом времени выполнения. Прочитайте Документы .

8 голосов
/ 12 января 2011

Я не знаю, кто сказал вам не использовать его, но они не правы.

  1. Даже если бы он был медленным, он никогда не был бы медленным до степени нарушения программы. Я никогда не замечал, что это слишком медленно.
  2. Это ключ к кроссплатформенному программированию. Разделители строк и т. Д. Различаются в зависимости от платформы, и os.path.join всегда будет правильно соединять пути независимо от платформы.
  3. читаемость. Все знают, что делает join. Людям, возможно, придется сделать двойную попытку для конкатенации строк для путей.
2 голосов
/ 21 января 2011

Также следует помнить, что периоды в вызовах функций, как известно, медленные. Для сравнения:

python -mtimeit -s "import os.path;x=range(10)" "os.path.join(x)"
1000000 loops, best of 3: 0.405 usec per loop

python -mtimeit -s "from os.path import join;x=range(10)" "join(x)"
1000000 loops, best of 3: 0.29 usec per loop

Так что это замедление на 40% только из-за наличия периодов в синтаксисе вызова функции.

Любопытно, что эти две скорости разные:

$ python -mtimeit -s "from os.path import sep;join=sep.join;x=map(str,range(10))" "join(x)"
1000000 loops, best of 3: 0.253 usec per loop

$ python -mtimeit -s "from os.path import join;x=map(str,range(10))" "join(x)"
1000000 loops, best of 3: 0.285 usec per loop
1 голос
/ 12 января 2011

Вы должны использовать os.path.join просто для переносимости.

Я не получаю смысла сравнивать os.path.join (который работает для любого числа или частей на любой платформе) с чем-то таким же тривиальным, как строкаформатирование двух путей.

Чтобы ответить на вопрос в заголовке: " Медленный ли файл os.path.join в Python? ", вы должны хотя бы сравнить его с удаленно подобной функцией, чтобы выяснитькакую скорость вы можете ожидать от такой функции.

Как вы можете видеть ниже, по сравнению с аналогичной функцией, нет ничего медленного в os.path.join:

python -mtimeit -s "x = tuple(map(str, range(10)))" "'/'.join(x)"
1000000 loops, best of 3: 0.26 usec per loop

python -mtimeit -s "from os.path import join;x = tuple(range(10))" "join(x)"
1000000 loops, best of 3: 0.27 usec per loop


python -mtimeit -s "x = tuple(range(3))" "('/%s'*len(x)) % x"
1000000 loops, best of 3: 0.456 usec per loop

python -mtimeit -s "x = tuple(map(str, range(3)))" "'/'.join(x)"
10000000 loops, best of 3: 0.178 usec per loop
1 голос
/ 12 января 2011

Это может быть почти в 50 раз быстрее, но если вы не делаете это в тесном внутреннем цикле, связанном с процессором, разница в скорости вообще не будет иметь значения.Разница в переносимости, с другой стороны, будет определять разницу между тем, может ли ваша программа быть легко перенесена на платформу, отличную от Unix.

Так что, пожалуйста, используйте os.path.join, если вы не профилировали и не обнаружиличто это действительно является серьезным препятствием для производительности вашей программы.

0 голосов
/ 21 января 2011

В этом горячем споре, я смею предложить:

(я знаю, я знаю, время есть, но я не так хорошо обучен, и clock () мне кажется достаточным для этого случая)

import os
from time import clock

separ = os.sep
ospath = os.path
ospathjoin = os.path.join

A,B,C,D,E,F,G,H = [],[],[],[],[],[],[],[]
n = 1000

for essays in xrange(100):

    te = clock()
    for i in xrange(n):
        xa = os.path.join('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')
    A.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xb = ospath.join('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')
    B.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xc = ospathjoin('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')
    C.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xd = 'C:\WINNT\system32'+os.sep+'Microsoft\Crypto'+os.sep+'RSA\MachineKeys'
    D.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xe = '%s\\%s\\%s' % ('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')
    E.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xf = 'C:\WINNT\system32'+separ+'Microsoft\Crypto'+separ+'RSA\MachineKeys'
    F.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xg = os.sep.join(('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys'))
    G.append(clock()-te)


    te = clock()
    for i in xrange(n):
        xh = separ.join(('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys'))
    H.append(clock()-te)

print min(A), "os.path.join('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')"
print min(B), "ospath.join('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')"
print min(C), "ospathjoin('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')"
print min(D), "'C:\WINNT\system32'+os.sep+'Microsoft\Crypto'+os.sep+'RSA\MachineKeys'"
print min(E), "'%s\\%s\\%s' % ('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')"
print min(F), "'C:\WINNT\system32'+separ+'Microsoft\Crypto'+separ+'RSA\MachineKeys'"
print min(G), "os.sep.join('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')"
print min(H), "separ.join('C:\WINNT\system32','Microsoft\Crypto','RSA\MachineKeys')"
print 'xa==xb==xc==xd==xe==xf==xg==xh==',xa==xb==xc==xd==xe==xf==xg==xh

результат

0.0284533369465 os.path.join ('C: \ WINNT \ system32', 'Microsoft \ Crypto', 'RSA \ MachineKeys')

0.0277652606686 ospath.join ('C: \ WINNT \ system32', 'Microsoft \ Crypto', 'RSA \ MachineKeys')

0.0272489939364 ospathjoin ('C: \ WINNT \ system32', 'Microsoft \ Crypto', 'RSA \ MachineKeys')

0,00398598145854 'C: \ WINNT \ system32' + os.sep + 'Microsoft \ Crypto' + os.sep + 'RSA \ MachineKeys'

0,00375075603184 '% s \% s \% s'% ('C: \ WINNT \ system32', 'Microsoft \ Crypto', 'RSA \ MachineKeys')

0,00330824168994 'C: \ WINNT \ system32' + separ + 'Microsoft \ Crypto' + separ + 'RSA \ MachineKeys'

0,00292467338726 os.sep.join ('C: \ WINNT \ system32', 'Microsoft \ Crypto', 'RSA \ MachineKeys')

0,00261401937956 separ.join ('C: \ WINNT \ system32', 'Microsoft \ Crypto', 'RSA \ MachineKeys')

1024 * Правда *

с

separ = os.sep

ospath = os.path

ospathjoin = os.path.join

0 голосов
/ 12 января 2011

Каждый должен знать одну неожиданную особенность os.path.join ()

os.path.join( 'a', 'b' ) == 'a/b'
os.path.join( 'a', '/b' ) == '/b'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...