简体   繁体   English

Python的os.path.join很慢吗?

[英]Is Python's os.path.join slow?

I've been told os.path.join is horribly slow in python and I should use string concatenation ( '%s/%s' % (x, y) ) instead. 我被告知os.path.join在python中非常慢,我应该使用字符串连接( '%s/%s' % (x, y) )代替。 Is there really that big a difference and if so how can I track it? 是否真的存在很大差异?如果是这样,我该如何跟踪它?

$ 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

So yes, it's nearly 50 times slower. 所以是的,它慢了近50倍。 1 microsecond is still nothing though, so I really wouldn't factor the difference in. Use os.path.join : it's cross-platform, more readable and less bug-prone. 虽然1微秒仍然没有 ,所以我真的不会考虑其中的差异。使用os.path.join :它是跨平台的,更具可读性且不易出错。

EDIT: Two people have now commented that the import explains the difference. 编辑:两个人现在评论说import解释了差异。 This is not true, as -s is a setup flag thus the import is not factored into the reported runtime. 这不是真的,因为-s是一个设置标志,因此import不会计入报告的运行时。 Read the docs . 阅读文档

I don't know who told you not to use it, but they're wrong. 我不知道是谁告诉你不要使用它,但他们错了。

  1. Even if it were slow, it would never be slow to a program-breaking extent. 即使它很慢,但程序破坏程度也永远不会慢。 I've never noticed it being remotely slow. 我从来没有注意到它的速度很慢。
  2. It's key to cross-platform programming. 这是跨平台编程的关键。 Line separators etc. differ by platform, and os.path.join will always join paths correctly regardless of platform. 行分隔符等因平台而异, os.path.join将始终正确地连接路径,而不管平台如何。
  3. Readability. 可读性。 Everyone knows what join is doing. 每个人都知道join正在做什么。 People might have to do a double take for string concatenation for paths. 人们可能不得不为路径的字符串连接做双重操作。

Also be aware that periods in function calls are known to be slow. 还要注意,函数调用中的句点已知很慢。 Compare: 相比:

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

So that's a slowdown of 40% just by having periods in your function invocation syntax. 因此,只需在函数调用语法中使用句点,就可以减慢40%。

Curiously, these two are different speeds: 奇怪的是,这两种速度不同:

$ 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

It may be nearly 50 times faster, but unless you're doing it in a CPU bound tight inner loop, the speed difference isn't going to matter at all. 它可能快近50倍,但除非你在CPU内部紧密的内环中进行,否则速度差异根本不重要。 The portability difference on the other hand will make the difference between whether or not your program can be easily ported to a non-Unix platform or not. 另一方面,可移植性差异将决定您的程序是否可以轻松移植到非Unix平台。

So, please use os.path.join unless you've profiled and discovered that it really is a major impediment to your program's performance. 因此,请使用os.path.join除非您已经分析并发现它确实是您程序性能的主要障碍。

You should use os.path.join simply for portability. 您应该使用os.path.join简化可移植性。

I don't get the point of comparing os.path.join (which works for any number or parts, on any platform) with something as trivial as string formatting two paths. 我没有把os.path.join (适用于任何数字或部件,在任何平台上)与点字符串格式化两个路径的事情进行比较。

To answer the question in the title, " Is Python's os.path.join slow? " you have to at least compare it with a remotely similar function to find out what speed you can expect from a function like this. 要回答标题中的问题,“ Python的os.path.join是慢吗? ”你必须至少将它与远程类似的函数进行比较,以找出你可以从这样的函数中获得什么样的速度。

As you can see below, compared to a similar function, there is nothing slow about os.path.join : 正如您在下面看到的,与类似的函数相比, 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

In this hot controversy, I dare to propose: 在这场炙手可热的争议中,我敢于提出:

(I know, I know , there is timeit, but I'm not so trained with timeit, and clock() seems to me to be sufficient for the case) (我知道,我知道,有时间,但我没有接受过timeit训练,而且我觉得时钟()对于这个案子来说已经足够了)

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

result 结果

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

0.0277652606686 ospath.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.0272489939364 ospathjoin('C:\\ WINNT \\ system32','Microsoft \\ Crypto','RSA \\ MachineKeys')

0.00398598145854 'C:\\WINNT\\system32'+os.sep+'Microsoft\\Crypto'+os.sep+'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.00375075603184'%s \\%s \\%s'%('C:\\ WINNT \\ system32','Microsoft \\ Crypto','RSA \\ MachineKeys')

0.00330824168994 'C:\\WINNT\\system32'+separ+'Microsoft\\Crypto'+separ+'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.00292467338726 os.sep.join('C:\\ WINNT \\ system32','Microsoft \\ Crypto','RSA \\ MachineKeys')

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

True 真正

with

separ = os.sep separ = os.sep

ospath = os.path ospath = os.path

ospathjoin = os.path.join ospathjoin = os.path.join

Everyone sholud know one inevident feature of os.path.join() 每个人都知道os.path.join()的一个不可思议的特性

os.path.join( 'a', 'b' ) == 'a/b'
os.path.join( 'a', '/b' ) == '/b'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM