【问题标题】:Open file in a relative location in Python在 Python 中的相对位置打开文件
【发布时间】:2011-11-02 04:55:28
【问题描述】:

假设我的python代码在一个名为main的目录中执行,应用程序需要访问main/2091/data.txt

我应该如何使用open(location)?参数location应该是什么?

我发现下面的简单代码可以工作..它有什么缺点吗?

file = "\2091\sample.txt"
path = os.getcwd()+file
fp = open(path, 'r+');

【问题讨论】:

  • 您正在使用未转义的反斜杠。这是一个缺点。
  • 几个缺点。 1)根据@orip,对路径使用正斜杠,即使在Windows上也是如此。你的字符串不起作用。或者使用像r"\2091\sample.txt" 这样的原始字符串。或者像"\\2091\\sample.txt" 一样逃避它们(但这很烦人)。另外,2)您正在使用 getcwd() ,这是您执行脚本时所在的路径。我以为你想要相对于脚本位置(但现在我想知道)。 3),始终使用os.path 函数来操作路径。你的路径加入线应该是os.path.join(os.getcwd(), file) 4) ;没有意义
  • 为了更好的衡量... 5) 使用上下文保护来保持它的清洁并避免忘记关闭你的文件:with open(path, 'r+') as fp:。请参阅 here 以获得对我所见过的 with 语句的最佳解释。
  • 除了对斜线的必要注意之外,正如刚才所指出的,还有os.path.abspath 函数可以轻松获取要打开的相对路径的完整路径。最终声明如下所示:os.path.abspath('./2091/sample.txt')

标签: python file path relative-path


【解决方案1】:

这取决于您使用的操作系统。如果您想要一个与 Windows 和 *nix 兼容的解决方案,例如:

from os import path

file_path = path.relpath("2091/data.txt")
with open(file_path) as f:
    <do stuff>

应该可以正常工作。

path 模块能够为其运行的任何操作系统格式化路径。此外,只要您拥有正确的权限,python 就可以很好地处理相对路径。

编辑

正如 kindall 在 cmets 中提到的,python 无论如何都可以在 unix 风格和 windows 风格的路径之间转换,所以更简单的代码也可以工作:

with open("2091/data/txt") as f:
    <do stuff>

话虽如此,path module 仍然有一些有用的功能。

【讨论】:

  • relpath() 将路径名转换为相对路径。由于它已经是相对路径,所以它什么也不做。
  • 如果合适的话,它将把它从一个unix风格的路径转换成windows风格的路径。 os.path 模块中是否还有其他功能会是更好的选择?
  • Windows 已经可以使用 UNIX 样式的路径正常工作。至少基于 NT 的系列会(2000、XP、Vista、7)。无需转换。
  • 这个答案不太正确,会引起问题。默认情况下,相对路径是相对于当前工作目录(执行脚本的路径),而不是实际的脚本位置。您需要使用__file__。请看我的回答。
  • 这个答案的作者是否将 os.path.relpath 与 os.path.abspath 混淆了?
【解决方案2】:

Python 只是将你给它的文件名传递给操作系统,操作系统会打开它。如果您的操作系统支持像 main/2091/data.txt 这样的相对路径(提示:它支持),那么这将正常工作。

您可能会发现回答此类问题的最简单方法是尝试一下,看看会发生什么。

【讨论】:

  • 不正确...脚本中的工作目录是您运行脚本的位置,不是脚本的位置。如果您从其他地方运行脚本(可能脚本在您的系统路径中),子目录的相对路径将不起作用。请参阅我关于如何解决此问题的答案。
  • @Russ - OP 的示例使用 getcwd()。我将原始描述阅读为“相对于我运行脚本的位置,无论代码位于何处”。
  • @orip - OP 在问题后 3 小时添加了 getcwd() 调用。没关系……继续。 :)
【解决方案3】:

使用这种类型的东西,您需要注意您的实际工作目录是什么。例如,您可能不会从文件所在的目录运行脚本。在这种情况下,您不能只使用相对路径本身。

如果您确定您想要的文件位于脚本实际所在的子目录下,您可以使用__file__ 来帮助您。 __file__ 是您正在运行的脚本所在的完整路径。

所以你可以摆弄这样的东西:

import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)

【讨论】:

  • 我发现下面的简单代码可以工作..它有什么缺点吗?
     file="\sample.txt" path=os.getcwd()+str(loc)+file fp=open(path,'r+');
  • @Arash 这样做的缺点是 cwd(当前工作目录)可以是任何东西,不一定是您的脚本所在的位置。
  • __file__ 是一个相对路径(至少在我的设置中,出于某种原因),您需要先调用os.path.abspath(__file__)。 osx/自制 2.7
  • os.path.dirname(file) 在 Python 2.7 中对我不起作用。它显示NameError: name '__file__' is not defined
  • @Soumendra 我认为您正在控制台中尝试它。在 *.py 文件中尝试。
【解决方案4】:

不确定这是否适用于任何地方。

我在 ubuntu 中使用 ipython。

如果要读取当前文件夹子目录下的文件:

/current-folder/sub-directory/data.csv

您的脚本在当前文件夹中 试试这个:

import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)

【讨论】:

    【解决方案5】:

    我创建了一个帐户,以便澄清我认为在 Russ 的原始回复中发现的差异。

    供参考,他原来的回答是:

    import os
    script_dir = os.path.dirname(__file__)
    rel_path = "2091/data.txt"
    abs_file_path = os.path.join(script_dir, rel_path)
    

    这是一个很好的答案,因为它正在尝试动态创建所需文件的绝对系统路径。

    Cory Mawhorter 注意到 __file__ 是一个相对路径(在我的系统上也是如此)并建议使用 os.path.abspath(__file__)。但是,os.path.abspath 返回当前脚本的绝对路径(即/path/to/dir/foobar.py

    要使用此方法(以及我最终如何使用它),您必须从路径末尾删除脚本名称:

    import os
    script_path = os.path.abspath(__file__) # i.e. /path/to/dir/foobar.py
    script_dir = os.path.split(script_path)[0] #i.e. /path/to/dir/
    rel_path = "2091/data.txt"
    abs_file_path = os.path.join(script_dir, rel_path)
    

    生成的 abs_file_path(在本例中)变为:/path/to/dir/2091/data.txt

    【讨论】:

    • 你甚至可以结合这两种方法来获得更简单的os.path.dirname(os.path.abspath(__file__))
    • @LukeTaylor 实际上,这比我去年在回答中尝试自己复制 os.path.dirname 功能要好。
    【解决方案6】:

    这段代码运行良好:

    import os
    
    
    def readFile(filename):
        filehandle = open(filename)
        print filehandle.read()
        filehandle.close()
    
    
    
    fileDir = os.path.dirname(os.path.realpath('__file__'))
    print fileDir
    
    #For accessing the file in the same folder
    filename = "same.txt"
    readFile(filename)
    
    #For accessing the file in a folder contained in the current folder
    filename = os.path.join(fileDir, 'Folder1.1/same.txt')
    readFile(filename)
    
    #For accessing the file in the parent folder of the current folder
    filename = os.path.join(fileDir, '../same.txt')
    readFile(filename)
    
    #For accessing the file inside a sibling folder.
    filename = os.path.join(fileDir, '../Folder2/same.txt')
    filename = os.path.abspath(os.path.realpath(filename))
    print filename
    readFile(filename)
    

    【讨论】:

    • 对我来说访问当前文件夹的父文件夹中的文件不起作用.. .. 被添加为字符串..
    • 在 Windows 上不起作用。文件路径正确,但 Python 状态为“找不到文件”并显示带有 \\ 分隔符的路径。
    • 在 Ubuntu 和 python3 中,我不得不引用 '__file__' 的引号,所以它变成了:fileDir = os.path.dirname(os.path.realpath(__file__))
    【解决方案7】:

    如果文件在您的父文件夹中,例如。 follower.txt,你可以简单地使用open('../follower.txt', 'r').read()

    【讨论】:

      【解决方案8】:

      试试这个:

      from pathlib import Path
      
      data_folder = Path("/relative/path")
      file_to_open = data_folder / "file.pdf"
      
      f = open(file_to_open)
      
      print(f.read())
      

      Python 3.4 引入了一个新的标准库来处理文件和路径,称为 pathlib。它对我有用!

      【讨论】:

      • 请改用with data_folder.open() as f
      【解决方案9】:

      我花了很多时间来发现为什么我的代码在 Windows 系统上找不到运行 Python 3 的文件。所以我加了。之前 / 一切正常:

      import os
      
      script_dir = os.path.dirname(__file__)
      file_path = os.path.join(script_dir, './output03.txt')
      print(file_path)
      fptr = open(file_path, 'w')
      

      【讨论】:

      • 更好:file_path = os.path.join(script_dir, 'output03.txt')
      • 我在 Windows 操作系统上试过,但没有成功。
      • 有趣 - 你能打印 script_dir 吗?然后将其转换为绝对路径,如script_dir = os.path.abspath(os.path.dirname(__file__))
      • 我会试试的,如果我成功了,我会改变答案。
      【解决方案10】:

      代码:

      import os
      script_path = os.path.abspath(__file__) 
      path_list = script_path.split(os.sep)
      script_directory = path_list[0:len(path_list)-1]
      rel_path = "main/2091/data.txt"
      path = "/".join(script_directory) + "/" + rel_path
      

      说明:

      导入库:

      import os
      

      使用__file__获取当前脚本的路径:

      script_path = os.path.abspath(__file__)
      

      将脚本路径分成多个项目:

      path_list = script_path.split(os.sep)
      

      删除列表中的最后一项(实际的脚本文件):

      script_directory = path_list[0:len(path_list)-1]
      

      添加相对文件的路径:

      rel_path = "main/2091/data.txt
      

      加入列表项,并添加相对路径的文件:

      path = "/".join(script_directory) + "/" + rel_path
      

      现在您可以对文件执行任何操作,例如:

      file = open(path)
      

      【讨论】:

      • 你应该使用path = os.path.join(script_directory, rel_path)中的os模块而不是path = "/".join(script_directory) + "/" + rel_path。而不是手动解析路径你应该使用script_path = os.path.dirname(__file__)
      【解决方案11】:
      import os
      def file_path(relative_path):
          dir = os.path.dirname(os.path.abspath(__file__))
          split_path = relative_path.split("/")
          new_path = os.path.join(dir, *split_path)
          return new_path
      
      with open(file_path("2091/data.txt"), "w") as f:
          f.write("Powerful you have become.")
      

      【讨论】:

        【解决方案12】:

        当我还是初学者时,我发现这些描述有点吓人。一开始我会尝试 For Windows

        f= open('C:\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
        print(f) 
        

        这会引发syntax error。我曾经很困惑。然后在谷歌上浏览了一番之后。找到了错误发生的原因。 为初学者写这篇文章

        这是因为要在 Unicode 中读取路径,您只需在启动文件路径时添加 \

        f= open('C:\\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
        print(f)
        

        现在只需在启动目录之前添加\即可。

        【讨论】:

        • 反斜杠是多个字符的转义字符。如果您碰巧遇到\t,例如\top\directory,则'\t' 会被解释为制表符,并且您的'trick' 会失败。最好的选择是使用原始字符串格式r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt',它不会尝试“转义”字符。
        【解决方案13】:

        获取父文件夹的路径,然后os.join你的相关文件到最后。

        # get parent folder with `os.path`
        import os.path
        BASE_DIR = os.path.dirname(os.path.abspath(__file__))
        file = "config.yaml"
        final_path = os.path.join(BASE_DIR, file)
        
        # get parent folder with `pathlib`'s Path
        from pathlib import Path
        BASE_DIR = Path(__file__).absolute().parent
        file = "config.yaml"
        final_path = BASE_DIR / file
        

        【讨论】:

        • 所有大写的名字都应该保留给常量
        • 在这种情况下,BASE_DIR 不是常量吗?正在运行的脚本的父文件夹在运行时不会改变。
        【解决方案14】:

        Since Python 3.4你可以以面向对象的方式访问对象:

        folder = Path(os.getcwd())
        path = folder / "2091" / "sample.txt"
        with path.open('r+') as fp:
            # do magic
        

        with 关键字还将确保您的资源正确关闭,即使您遇到了一些讨厌的Exception

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多