Package: relpath
relpath下の方に日本語の説明があります底下有中文解释。Summary (Explanation in English)Features of this packageyou can use the relative path intuitivelyThe standard relative path in python is not intuitive.you can import various modules relativelyIt can handle complex projects where the folders are nested.Usage #1: A basic exampleExample of getting the directory (location) of the python file itselffromrelpathimportrel2absprint(rel2abs("./"))# -> "(The directory this python file belongs to)"Usage #2: A Practical ExampleA practical use case for this tool.
`-- project_folder
    |-- parts
    |   |-- data.txt
    |   `-- script_B.py
    `-- script_A.pyAs shown above, consider a project with multiple python files.
Inscript_A.py, we will usescript_B.pyas shown below.# script_A.py# load script_B.pyfromparts.script_Bimportget_dataprint(get_data())In this case, if you try to refer to"./data.txt"relatively fromscript_B.py, as shown in the following code example, it will fail. (Note 1)(Note 1)
Strictly speaking, you can load it by specifying a relative path from `script_A.py`,
but if the caller is changed to another location, it won't work properly and is not easy to maintain.
To avoid this, we recommend using the `relpath` package.# script_B.pydefget_data():withopen("./data.txt","r")asf:# -> FileNotFoundError: [Errno 2] No such file or directory: './data.txt'returnf.read()On the other hand, you can use therelpathpackage and write the following to refer to"./data.txt"relatively. (Note 2)# script_B.pyfromrelpathimportrel2absdefget_data():withopen(rel2abs("./data.txt"),"r")asf:# -> NO ERROR!!returnf.read()(Note 2)
The python specification of relative paths is not necessarily wrong.
Under the python specification, a relative path is always interpreted with the first executed python file as the reference position.
So users have to be aware of the position of the first executed python file
when writing a relative path.
On the other hand, the python specification has an advantage:
if the file containing the path is moved, you don't have to change the path.
The `relpath` package is just another way to give the programmer another option besides the python specification,
so we recommend that you consider whether to use it or not depending on the situation.Usage #3: Relative import exampleTherelpathpackage provides an intuitive relative import of a module, as shown in the following example.fromrelpathimportadd_import_pathadd_import_path("../")frommy_moduleimportsome_functionsome_function()Why do I need to write like the above example? Can't I just writesys.path.append("../")?
As a matter of fact,sys.path.append("../")does not work well if your project folder has a complex hierarchical structure where one module is used from different locations.
Therefore, it is recommended to use theadd_import_pathof therelpathpackage whenever you want to implement relative import.add_import_path("../")is internally equivalent tosys.path.append(rel2abs("../")).概要 (日本語)このパッケージでできること:直感的な相対パス参照ができるpythonのパス参照の仕様は直感に反するモジュールの相対importに使えるフォルダが多重で複雑なプロジェクトにも対応できる使い方1: 基本的な例下記は、pythonファイル自身の場所(ディレクトリ)を取得する例です。fromrelpathimportrel2absprint(rel2abs("./"))# -> "(このpythonファイルが存在するディレクトリ)"使い方2: 実用的な例このツールは、下記のような場合に真価を発揮します。.
`-- project_folder
    |-- parts
    |   |-- data.txt
    |   `-- script_B.py
    `-- script_A.py上記のように、複数のpythonファイルからなるプロジェクトを考えます。script_A.pyの中では下記のように、script_B.pyを利用します。# script_A.py# load script_B.pyfromparts.script_Bimportget_dataprint(get_data())この場合に、下記のコード例のように、script_B.pyから"./data.txt"を相対的に読み込もうとすると失敗します。(注1)(注1)
厳密には、`script_A.py`からの相対パス指定をすれば読み込めますが、
呼び出し元が別の場所に変更された場合、正常に動作しなくなるので、メンテナンス性が悪くなります。
これを回避するため、`relpath`パッケージの利用を推奨します。# script_B.pydefget_data():withopen("./data.txt","r")asf:# -> FileNotFoundError: [Errno 2] No such file or directory: './data.txt'returnf.read()そこで、relpathパッケージを使って下記のように書くと、"./data.txt"を相対的に読み込めるようになります。(注2)# script_B.pyfromrelpathimportrel2absdefget_data():withopen(rel2abs("./data.txt"),"r")asf:# -> NO ERROR!!returnf.read()(注2)
相対パスに関するpythonの仕様は、必ずしも間違いというわけではありません。
pythonの仕様(相対パスの指定が、記述するファイルの場所に関わらず、常に最初の呼び出し元を基準として解釈される仕様)には、
プログラムを開発する中でもしファイル読み込み等の命令を記述する場所(ファイル)が変更になった場合でも、
パス指定方法の変更が不要になるという利点があります。
`relpath`パッケージは、pythonの仕様の他に、プログラマーにもう一つの選択肢を与える手段に過ぎないので、
状況に応じて利用の要否を検討することを推奨します。使い方3: 相対importとしての利用relpathパッケージを利用すると、下記の例のように、
モジュールの直感的な相対importを実現できます。fromrelpathimportadd_import_pathadd_import_path("../")frommy_moduleimportsome_functionsome_function()上記の例を見ると、単にsys.path.append("../")としても動作するように思われます。
しかし、プロジェクトフォルダの階層構造が複雑で、1つのモジュールが別々の場所から使われるような場合には、sys.path.append("../")では対応できないことがあります。
そのため、相対importを実現したいときは、常にrelpathパッケージのadd_import_pathを利用することを推奨します。なお、add_import_path("../")は、内部的にはsys.path.append(rel2abs("../"))と等価です。摘要 (中文解释)本套餐的特点你可以直观地使用相对路径。python中标准的相对路径并不直观。可以相对导入各种模块它可以处理文件夹嵌套的复杂项目。用法 #1: 一个基本的例子获取python文件本身的目录（位置）的例子fromrelpathimportrel2absprint(rel2abs("./"))# -> "(这个python文件所属的目录)"用法 ＃2: 一个实际例子该工具的实际使用案例.
`-- project_folder
    |-- parts
    |   |-- data.txt
    |   `-- script_B.py
    `-- script_A.py如上图所示，考虑一个有多个python文件的项目。
在script_A.py中，我们将使用script_B.py，如下所示。# script_A.py# load script_B.pyfromparts.script_Bimportget_dataprint(get_data())在这种情况下，如果你试图从script_B.py中相对引用"./data.txt"，如下面的代码示例所示，它将失败。 (注1)(注1)
严格来说，你可以通过指定`script_A.py`的相对路径来加载，
但如果调用者换到其他位置，就不能正常工作，而且不容易维护。
为了避免这种情况，我们建议使用`relpath`包。# script_B.pydefget_data():withopen("./data.txt","r")asf:# -> FileNotFoundError: [Errno 2] No such file or directory: './data.txt'returnf.read()另一方面，你可以使用relpath包，并写下以下内容来相对引用"./data.txt"。 (注2)# script_B.pyfromrelpathimportrel2absdefget_data():withopen(rel2abs("./data.txt"),"r")asf:# -> NO ERROR!!returnf.read()(注2)
相对路径的python规范不一定是错的。
在python规范下，相对路径总是被理解为相对于第一个执行的Python文件作为参考位置。
所以用户在写相对路径的时候，要注意第一个执行的python文件的位置。
另一方面，python规范至少有一个优点。
其优点是，当移动包含路径的文件时，不需要改变路径。
`relpath`包只是给程序员在python规范之外的另一种选择，所以建议大家根据实际情况考虑是否使用。用法 #3: 相对导入示例relpath包提供了一个直观的模块相对导入，如下例所示。fromrelpathimportadd_import_pathadd_import_path("../")frommy_moduleimportsome_functionsome_function()为什么要写成上面的例子？ 我不能直接写sys.path.append("../")吗？
事实上，如果你的项目文件夹具有复杂的层次结构，一个模块从不同的位置使用，sys.path.append("../")就不能很好地发挥作用。
因此，当你想实现相对导入时，建议使用relpath包中的add_import_path。add_import_path("../")内部等同于sys.path.append(rel2abs("../"))。