我就是一个使用当前路径的受害者,而且被困扰了2次,不过最后终于还是找出了原因所在,下面将其与大家分享一下。第一次是用Python写了一个备
份程序,程序主要由3个文件组成:backup.py、config.ini和backup.log,config.ini主要用于设置备份任务的各种
参数,backup.py是通过当前路径的方式来读取config.ini的设置,该程序在Windows和Linux下测试都完全正常,但是在
Linux下通过cron来部署计划任务的时候出现了问题,程序怎么也不能自动运行,当时因为某些原因没有仔细去查原因到底出在什么地方。第二次是我们
要用Python写一个自动更新的程序,它也是由一个主程序去读取一个配置文件来查找服务器的相关信息。该程序在测试时也没有问题,但是通过
py2exe打包成exe并通过Windows的计划任务来部署测试的时候发现程序并没有运行成功,当时非常奇怪,因为不知道问题出现在了什么地方,一
点头绪都没有,然后就是漫长的调试过程,最终发现问题出在读取config.ini这个文件上。通过打印发现当前路径是C:\Windows
\system32,这才想到当前路径是当前的工作路径,并不是当前执行程序文件的路径。
问题找到了,剩下的就是解决问题了。Python下有2个方式是与获取当前路径相关的,一个是os.getcwd(),另外一个是sys.path
[0]。os.getcwd()实际上就是获取当前工作路径(current working directory),而sys.path[0]是当前
运行的脚本文件所在的目录(the directory containing the script that was used to
invoke the Python interpreter)。很显然os.getcwd()不适合,我们只能从sys.path[0]下手,因为他
的doc解释好像正好是我的那两个程序所需要的,然后兴奋的试了一下,改完程序:os.path.join(sys.path[0],
'config.ini'),直接运行程序测试,没有问题。然后打包成exe,配置计划任务后,结果运行失败!没辙了,再打印一下路径看看,发现
sys.path[0]返回的值并不是想象中的那样是一个目录,而是那个可执行文件:E:\test\updater.exe。
问题出来了,sys.path[0]在Python脚本文件中返回的是文件夹的路径E:\test(脚本路径为E:\test
\updater.py),而通过py2exe打包后的exe文件返回的却是该exe的路径E:\test\updater.exe(exe程序路径为
E:\test\updater.exe),为了兼容这两种方式写了一个函数用于获取当前路径:
def getpwd():
pwd = sys.path[0]
if os.path.isfile(pwd):
pwd = os.path.dirname(pwd)
return pwd
至此,问题解决。
上面的解决说实在的,感觉有问题:
1. config.ini所在的目录应该是运行目录,而不是当前目录。当前目录有可能随时在变,而运行目录则与程序所在的位置有关。
2. sys.path是Python导入模块时搜索的目录,与当前目录无关。在windows下会自动将运行所在的目录加入sys.path,在linux可能就不同的。不知道你在linux下试过吗?
其实你的问题应该是:config.ini与执行文件是在一个目录下或是根据执行文件可以找到config.ini文件。因此只要找到执行文件所在的目录就可以找到config.ini了。并不需要当前目录。应该是使用
os.path.dirname(sys.argv[0])
当运行时sys.argv[0]就是你执行文件的命令行,通过os.path.dirname()可以得到它的目录。它可以是相对路径也可以是绝对路径。
另外如果你是想找导入某个模块相关的文件,可以在导入模块后使用mod.__path__[0]找到它的路径,或os.path.dirname(mod.__file__)找到路径。
--
I like python!
UliPad <<The Python Editor>>: http://code.google.com/p/ulipad/
UliWeb <<simple web framework>>: http://uliwebproject.appspot.com
My Blog: http://hi.baidu.com/limodou
问题还是在于你们用工作目录作为执行目录了,
又将执行目录视为"当前路径"。
你在命令行下执行当前目录里的 python 程序时,
这几个目录都是一样的,所以也就忽视了他们的差别。
另外, Windows 下的程序快捷方式,通常都加了相同的工作路径(属性里的"起始位置")
以致有人说"Linux 下不一样"之类。
腾讯出的 Linux QQ 同样有类似的问题,以致腾讯的人得用个脚本先 cd 到程序目录,再来执行
linux下快捷方式不能设置"起始位置"确实不太方便,比如我想把python的html格式的document在桌面上建立一个快捷方式,就不行,链接地址都不对,只能先cd到目录下。
2009/2/22 Jiahua Huang <jhuang...@gmail.com>:
根据sys.argv[0]就可以处理了啊。
问题是没有必要啊,
程序你用执行目录换掉工作目录就好(那才是你要的"当前路径")。
而你 html 的"快捷方式",估计其实是软连接,
软连接当然不能有所谓"起始位置", 你用 Windows 的 NTFS 软连接也是一样的。
况且 Linux 下时常会要能从命令行启动,而不是依赖特定的快捷方式( .desktop 菜单项),
这工作路径就是命令行路径了(并非只有终端才是命令行,其他程序调用也是命令行的)
Linux下通过cron来部署计划任务的时候出现了问题,程序怎么也不能自动运行,当时因为某些原因没有仔细去查原因到底出在什么地方。
Long 写道:
补充一下,Mac和Linux也会将当前执行目录放入sys.path,也就是说sys.path[0]
和sys.argv[0]的内容是一样的(至少Python 2.5下是这样的)。
总之,举例来讲,os.getcwd()、sys.path[0] (sys.argv[0])和__file__的区别
是这样的:
假设目录结构是:
C:\test
|
[dir] getpath
|
[file] path.py
[dir] sub
|
[file] sub_path.py
然后我们在C:\test下面执行python getpath/path.py,这时sub_path.py里面与各
种用法对应的值其实是:
* os.getcwd() “C:\test”,取的是起始执行目录
* sys.path[0]或sys.argv[0] “C:\test\getpath”,取的是被初始执行的脚本的
所在目录
* os.path.split(os.path.realpath(__file__))[0] “C:\test\getpath\sub”,
取的是__file__所在文件sub_path.py的所在目录
--
----------------------------------------
Personal Site: http://www.elias.cn
----------------------------------------
放到site-packages里去行不行
--
Any complex technology which doesn’t come with documentation must be the best
available.
设置PYTHONPATH或每次执行都执行它。
我想就这个话题问个别的我自己写的module,因为怕乱,不想存放在python的sys.path中,也不用sys.path.append()方法添加,有没有别的方法使得python能找到我的module ?再问下,我试过sys.path.append()不是永久性的,如果能让它变成永久性的,如何做
On 3月21日, 下午12时38分, limodou <limo...@gmail.com> wrote:
> 2009/3/21 zanpen2000 <zanpen2...@gmail.com>:
2009/2/23 kilnt <kiln...@gmail.com>:
--
HD(燃烧中的火)
我工作我快乐,我勤奋我收获。请与我一起快乐,与我一起收获。