Python中类似Matlab addpath的功能

4

Python是否有类似于Matlab的addpath的功能?我知道sys.path.append,但那似乎只适用于Python文件/模块,而不适用于普通文件。

假设我有一个配置文件config.txt在C:\ Data中,当前工作目录是其他地方,例如D:\ my_project。

我想要类似于以下代码:

def foo():
    with open('config.txt') as f:
        print(f.read())

def main():
    addpath(r'C:\Data')
    foo()

很显然,我可以在这里传递路径给foo,但在实际使用中这非常困难。

1
MATLAB的addpath不是用来添加数据文件路径的。它与load一起使用,以便用户可以加载随工具箱提供的示例数据集,但它并不适用于一般情况。这是不好的做法。 - Cris Luengo
5个回答

4

您不能像在Matlab中那样添加多个路径。

您可以使用os.chdir更改目录,并从该目录访问文件和子目录:

import os

def foo():
    with open('config.txt') as f:
        print(f.read())

def main():
    os.chdir(r'C:\Data')
    foo()

为了管理多个目录,使用一个上下文管理器,在上下文过期后返回到之前的目录是可行的:

import contextlib
import os

@contextlib.contextmanager
def working_directory(path):
    prev_cwd = os.getcwd()
    os.chdir(path)
    yield
    os.chdir(prev_cwd)

def foo():
    with open('config.txt') as f:
        print(f.read())

def main():
    with working_directory(r'C:\Data'):
        foo()
    # previous working directory

如果你只想添加一个路径,那么这个方法是可行的,但是使用Matlab,你可以添加多个路径,这个方法可能无法模拟。 - user2133814
@user2133814 嗯,这至少可以帮助您在文件系统上更改路径,并确切地知道您所在的位置。 - Moses Koledoye
1
@Moses Koledoye,我遇到了与user2133814相同的问题。您提出的“contextlib”想法对我很有效。我应该使用这个。谢谢。 - IanHacker

3
不,Python不是这样工作的。文件是从当前工作目录或特定的、已解决的路径加载的。没有预定义的加载任意文件的路径集合。在Python(以及除MATLAB之外的大多数编程语言)中,将数据和程序逻辑分开是一个重要的概念。Python的一个关键原则是“显式优于隐式”。确保要加载的数据文件被明确定义是更安全、更可靠、更少出错的做法。因此,尽管其他人已经展示了如何通过一些变通方法来实现,我强烈建议你不要使用这种方法。它会让维护你的代码变得更加困难。

我对此感到惊讶。我一直觉得Python在过于开放和灵活方面出现了错误。软件中的许多事情通常是一个坏主意,但仍然具有非常重要的用例,例如Python的多重继承和Java的反射。 - user2133814
1
“除了MATLAB之外的大多数编程语言”——这是不正确的。MATLAB和其他编程语言一样喜欢数据和代码之间的分离。我不知道这个评论从哪里来。 - Cris Luengo
@CrisLuengo 我们正在讨论的问题就是一个明显的例子,它明确将数据和逻辑视为等同的。但这并不是孤立的例子。该语言是围绕脚本和简单的一次性函数构建的。直到最近,它才提供了对比那更结构化的代码的任何支持,而且这种支持仍然不完善。它甚至直到最近才提供了向他人分发代码的支持。而且,编写通用代码仍然非常困难,需要大量检查以确保其结构正确。 - TheBlackCat
@TheBlackCat 我不同意。我在20多年前为MATLAB 5.3编写了一个高度复杂的大型工具箱。分发它没有任何问题,我们像当时分发所有其他软件一样,使用ZIP文件。当时没有任何平台的应用商店。构建那段代码并不比构建C语言中的大型库更难。我不明白你的批评从何而来,除非你不熟悉MATLAB。有很多事情可以批评MATLAB,但这不是其中之一。 - Cris Luengo
@CrisLuengo,这个问题的关键在于MATLAB明确地不区分代码和数据。MATLAB最初甚至没有支持函数,它纯粹是一个数据处理工具。像Python和Perl这样的工具在1990年代就有了包管理,而MATLAB要再等将近20年才能得到它,而且仍然比当时的Python差(例如没有依赖概念)。自1990年代以来,C和Python就已经有了导入/包含功能,而MATLAB要再等将近20年才能得到它。而且包仍然是一团糟(例如不相对),它们常常带来更多的麻烦而不是帮助。 - TheBlackCat
显示剩余2条评论

1

抱歉,我犯了一个错误。

我猜你可以使用这个来解决它。(作为一个新手,希望能够帮助到你)

import sys
sys.path.append(r'path')

原帖中提到:“我知道关于sys.path.append的事情”,然后解释了为什么它在他们的特定情况下没有用。我建议在回答问题之前,阅读问题标题以外的更多内容,特别是如果已经有很多答案了。 - Cris Luengo
T_T,非常抱歉。感谢您的建议,我会更加小心。 - bamboopu

1
你可以使用os.chdir功能和自己的open函数来检查所有你想要的路径。
class FileOpener(object):
    def __init__(self):
        self.paths = []
    def add_path(self, path):
        self.paths.append(path)
    def __open_path(self, path, *args, **kwargs):
        old_path = os.getcwd()
        try:
            os.chdir(path)
            return open(*args, **kwargs)
        except:
            pass
        finally:
            os.chdir(old_path)
    def open(self, *args, **kwargs):
        for path in self.paths + [os.getcwd()]:
            f = self.__open_path(path, *args, **kwargs)
            if f is not None:
                return f
        raise IOError("no such file")

my_file_opener = FileOpener()
my_file_opener.add_path("C:/Data")
my_file_opener.add_path("C:/Blah")
my_file_opener.open("some_file") # checks in C:/Data, C:/Blah and then the current working directory, returns the first file named "some_file" that it finds, and raises an IOError otherwise

0
def foo(prefix):
    path = prefix + 'config.txt'
    with open(path) as f:
        print(f.read())

def main():
    foo(r'C:\Data\')

---更新----

import os

class changeFileDir:
    def __init__(self, path):
        self.path= os.path.expanduser(path)

    def __enter__(self):
        self.savedPath = os.getcwd()
        os.chdir(self.path)

    def __exit__(self, etype, value, traceback):
        os.chdir(self.savedPath)


with changeFileDir(r'C:\Data'):
    foo()

正如我在问题中所说的那样,这对于这个简单的情况来说是一个显而易见的解决方案,但对于实际用例来说并不是真正可行的。此外,您应该使用 os.path.join。 - user2133814

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接