Emacs 下 Python 文件里调用 os.getcwd() 路径不对头

如图,

  • 在 Emacs 里运行该文件得到的 DIR 结果是 e:\\sourcecode\\leetcode
  • 在 IDLE 里运行该文件得到的 DIR 的结果是 E:\sourcecode\leetcode\Kaggle\Titanic

为啥 Emacs 里的 os.getcwd() 的路径不对头,我尝试过重新打开 Emacs 和该文件,但都是这个结果。请问大家有这个问题么?

cwd 是当前工作路径的意思,等于你调用这个脚本的所在的路径。

谢谢回复,因为我一开始是用相对寻址来找 train.csv 的,然后发现在 Emacs 里运行报错,发现可能是 current working dir 的事,所以就这样输出的看。

我比较好奇为啥当前文件路径是 E:\sourcecode\leetcode\Kaggle\Titanic\titanic.py,但是在 Emacs 里获得的 current working dir 却是 E:\sourcecode\leetcode,用 IDLE 就是正常的 E:\sourcecode\leetcode\Kaggle\Titanic

现在我利用 os.chdir() 改了 cwd 暂时解决了这个问题。

我发现坛里也有人遇到过这个问题 有用 lpy 的吗?交流一下

他是重启电脑解决的,我重启电脑、Emacs 都没效果。

「文件路径」跟「当前工作路径」没关系,也就是说os.getcwd() 返回值跟你的 Python 文件路径没关系,如果要获得「文件路径」你得使用 __file__

谢谢,我昨天试了链接里的 os.path.dirname(os.path.abspath(__file__)),但是报错 NameError: name '__file__' is not defined

参考 python NameError: global name ‘file’ is not defined 里的解决方案是得 python file.py 这样运行文件。

但是默认情况下『当前工作路径』应该就是当前文件所在的目录吧(还是我主观了)

我看 https://stackoverflow.com/a/45591911/10315163 这里说的大概也是这么个意思

On the other hand, if you start by editing or running a file within a specific directory, your location will be the folder of the file you were editing.

这个就是正确回复,可是刚刚不知道 markdown 里面怎么打出这个答案了,尴尬

Python里面所有都要用这个方式去获取当前文件所在的路径,要不然一旦你的 py 文件被软连接,路径就会完全变化。

但是使用 __file__ 的话,我看得 python file.py 这样运行。

一般 Emacs 里运行我是 C-c C-c,难道涉及到文件路径还要用 eshell 跑么?有没有啥简单一点的解决方案。

而且我的疑问:

也没有解决。

在交互环境都不会有文件的,所以会报错,只有在文件才有效,好好Google一下你就明白区别了

__file__ 这个是Python获取当前文件所在路径最标准的做法,其他拼凑路径的方法都是不对的,软连接或者其他任何方法都会导致非 __file__ 的路径方法失效。

但是 __file__ 在交互环境中文件不存在,导致这个方法不管用。

如果你的项目最终是以要有 py 文件的,就用 __file__, 早晚都绕不过去的,如果你就是在解释器里面测试,为啥不用绝对路径呢?反正都是测试。

image

我本意是想在 titanic.py 里使用 dataset 目录下的一些数据集的。因为一开始我用 .\dataset\train.csv 这样相对寻址来找的,但是在 Emacs 里这样会报错,用 IDLE 没问题。

所以我猜可能是 cwd 的问题,所以就拼凑路径成了题图那种奇怪的形式来测试一下问题在哪。

绝对路径也不是不可以,但是我想以后可能会移动文件啥的,就要改,会比较麻烦,所以写的是相对路径。

我的意思是,如果你只是测试,啥路径都可以。 但是如果你都要担心以后会移动路径啥的,__file__ 就是你要找的方案,因为你要移动文件,就意味着你要把你测试的代码固定下来,不会随着目录移动而出错。

那为什么不把你实验的代码写到 py 文件中并用 __file__ 呢?

任何Python项目都会有一个 main.py 的文件,你把你的实验代码写 __file__, 然后在 main.py import 你刚刚写的那个模块,不就行了吗?

谢谢,这个还是第一次有人跟我这样建议,感觉学到了不少,果然还是要多问多交流学的东西才多。 :smile: