【问题标题】:constructing absolute path with os.path.join()用 os.path.join() 构造绝对路径
【发布时间】:2013-06-30 00:35:32
【问题描述】:

我想在 python 中构建一个绝对路径,同时对路径分隔符之类的东西保持相当的清醒。

edit0: 例如,我的文件系统的根目录有一个目录 /etc/init.d(或 w32 上的 C:\etc\init.d),我只想从元素 etcinit.d(在 w32 上,我可能还需要一个磁盘 ID,例如 C:

为了不必担心路径分隔符,os.join.path() 显然是首选工具。但似乎这只会创建 relative 路径:

 print("MYPATH: %s" % (os.path.join('etc', 'init.d'),)
 MYPATH: etc/init.d

添加一个虚拟的第一个元素(例如'')没有任何帮助:

 print("MYPATH: %s" % (os.path.join('', 'etc', 'init.d'),)
 MYPATH: etc/init.d

将第一个元素设为绝对值显然有帮助,但这违背了使用os.path.join() 的想法

 print("MYPATH: %s" % (os.path.join('/etc', 'init.d'),)
 MYPATH: /etc/init.d

edit1: 使用os.path.abspath() 只会尝试将相对路径转换为绝对路径。 例如考虑在工作目录/home/foo 中运行以下命令:

 print("MYPATH: %s" % (os.path.abspath(os.path.join('etc', 'init.d')),)
 MYPATH: /home/foo/etc/init.d

那么,“root”路径的标准跨平台方式是什么?

 root = ??? # <--
 print("MYPATH: %s" % (os.path.join(root, 'etc', 'init.d'),)
 MYPATH: /etc/init.d

edit2: 问题归结为:由于/etc/init.d 中的前导斜杠使该路径成为绝对路径,有没有办法以编程方式构造该前导斜杠? (我不想假设前导斜杠表示绝对路径)

【问题讨论】:

  • 我不确定我是否正确阅读了您的问题,但您能否简单地说:os.path.abspath('python.exe') 在我的 Windows 机器上返回 'C:\\Python27\\python.exe'
  • 我已经更新了问题以(希望)澄清我想要什么。
  • 顺便说一句,相关的近乎重复:stackoverflow.com/questions/12041525/…
  • 这些答案都不适合我。我如何加入root_dir="C:/Users/folder"filename="data/file1.txt" 以获得绝对路径?在非 Windows 中使用 os.path.join(root_dir, filename) 很容易,但我在 Windows 中找不到解决方案。

标签: python path absolute-path


【解决方案1】:

使用 os.sep 作为 root 对我有用:

path.join(os.sep, 'python', 'bin')

Linux:/python/bin

Windows:\python\bin

path.abspath() 添加到组合中也会为您提供 Windows 上的驱动器号,并且仍然与 Linux 兼容:

path.abspath(path.join(os.sep, 'python', 'bin'))

Linux:/python/bin

Windows:C:\python\bin

【讨论】:

  • 似乎可以在 Linux 和 Win 上运行,所以 +1。但是感觉错了。可能会在其他一些晦涩的系统上中断,但我想不出。仍然觉得 python 应该给我们一个明确的方法来做到这一点。这取决于以路径分隔符开头的绝对路径。
【解决方案2】:

我认为你可以使用os.path.normpath。这是我在 Windows 上得到的:

>>> os.path.normpath("/etc/init.d")
'\\etc\\init.d'

我不确定驱动器前缀的正确做法是什么,但我认为将其关闭意味着“继续使用我现在打开的驱动器”,这可能是您想要的。也许更熟悉 Windows 的人可以澄清一下?

【讨论】:

  • 这是正确的答案,让python来确定你在哪个平台上
  • 我同意这种观点,但它使用的是完全合格的路径,而不是 os.path.join()。虽然知道它很有用,但它不能作为解决方案。
【解决方案3】:

所以你可以检查正在运行的操作系统 通过 sys.platfrom

在窗户上

>>> sys.platform
'win32'

在 Linux 上

>>> sys.platform
'linux2'

然后

if sys.platform == 'win32':
    ROOT = os.path.splitdrive(os.path.abspath('.'))[0]
elif sys.platform == 'linux2':
    ROOT = os.sep

请注意,'linux2' 可能不会涵盖所有的 linux 发行版

【讨论】:

  • 不,我真的想要我的文件系统的根目录(无论 python 模块位于何处)。 os.path.abspath('foo') 将返回(例如)/home/me/foo(如果我在 /home/me 内运行它)而我真的需要 /foo(或 C:\\foo
  • 我已经更新了问题以澄清为什么os.path.abspath() 似乎对我没有帮助。
  • 如果你想拥有一个不基于文件的根目录,并且特定项目中的所有文件都拥有相同的根目录。您可以将 ROOT(字符串值)存储在配置文件中,或者您可以通过在所有文件中的硬编码值来定义 ROOT。我已经在我的回答中添加了这个。
  • 问题是:是什么让/etc 成为绝对路径? (显然是/ 前缀,但是有没有一种程序化的方式来获取这个后缀?)
  • 好的。我想我明白了。有 os.path.splitdrive() 会返回驱动器 os.path.splitdrive(os.path.abspath('.')) 但在 linux 上它不会返回根目录,即。 '/'
【解决方案4】:

所以我想出的解决方案是通过跟随给定文件到它的根来构造文件系统的根:

def getRoot(file=None):
  if file is None:
      file='.'
  me=os.path.abspath(file)
  drive,path=os.path.splitdrive(me)
  while 1:
    path,folder=os.path.split(path)
    if not folder:
       break
  return drive+path

 os.path.join(getRoot(), 'etc', 'init.d')

【讨论】:

  • 甚至可以更简单:drive,path=os.path.splitdrive(me) if not drive: return os.path.split(path)[0] else: return drive
  • 嗯,我确信我的解决方案不是最 Pythonic 的方式;但是如果文件评估为/foo/bar/baz,您的解决方案将返回/foo/bar/baz(基本上是您为Ansuman的回答提到的问题)
  • 该死,你是对的。被关于 SO >. 的另一个答案误导了
  • 我觉得这很有趣,但我对为什么它仍然是公认的答案感到有些困惑。
【解决方案5】:

您可以尝试使用 os.path.splitdrive 来获取驱动器/文件系统的名称,然后将其与您的 foo 字符串连接。

http://docs.python.org/2/library/os.path.html#os.path.splitdrive

类似的东西(未经测试!)

(drive, tail) = os.path.splitdrive(os.getcwd())
os.path.join(drive, 'foo')

应该可以解决问题。

【讨论】:

  • 在 linux 上不起作用 - 驱动器被设置为 '' 并加入它不会给出根路径
猜你喜欢
  • 1970-01-01
  • 2012-11-23
  • 1970-01-01
  • 2018-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-15
  • 1970-01-01
相关资源
最近更新 更多