模块路径依赖
假设我们有一个项目的目录结构如下:
<root>
__init__.py
helloworld.py
<moduleOne>
f.txt
__init__.py
printfile.py
这里的 root 和 moduleOne 是文件夹。
helloworld.py 的内容是:
#!/usr/bin/python
import helloworld.printfile
printf()
moduleOne/printfile 的内容是:
#!/usr/bin/python
f = open('f.txt')
def printf():
print 'print file'
print f
if __name__ == '__main__':
printf()
我的问题是:
从 moduleOne/ 运行 printfile 是没问题的,但如果我从 root/ 运行 helloworld.py,就会出现以下错误:
import moduleOne.printfile
File "/root/moduleOne/printfile.py", line 5, in <module>
f = open('f.txt')
IOError: [Errno 2] No such file or directory: 'f.txt'
在 Python 中怎么解决这个问题?
[编辑]
我用一种“变通办法”解决了(或多或少)这个问题,但仍然有一个新问题:
我的解决方案是:
在 moduleOne/printfile 中:
import sys
fname = 'moduloOne/f.txt'
def printf():
f = open(fname)
print 'print file'
print f
if __name__ == '__main__':
fname = 'f.txt'
printf()
但是……
假设我在 root 下新建了一个叫 etc 的文件夹,那么新的结构是:
<root>
__init__.py
helloworld.py
<moduleOne>
f.txt
__init__.py
printfile.py
<etc>
f2.txt
现在我需要从 moduleOne/printfile 访问 etc/f2.txt,应该怎么做呢?
1 个回答
1
你需要更多的抽象。
- 不要在
printfile.py
中直接写死文件路径。 - 在
printf
函数中不要访问全局变量。 应该把文件句柄作为参数传给
printf
函数:def printf(file_handle): print 'print file' print file_handle
在一个确实需要知道
f.txt
路径的脚本中(我猜在你的例子中是helloworld.py
),把路径放在那儿,打开它,然后传给printf
:from moduleOne.printfile import printf my_f_file = open('/path/to/f.txt') printf(my_f_file)
更好的是,从命令行获取文件路径:
import sys from moduleOne.printfile import printf input_file_path = sys.argv[1] my_f_file = open(input_file_path) printf(my_f_file)
编辑:你在你的 Google+ 交叉发布中提到:
完整路径是个问题,程序会在不同的环境中运行。
如果你想把程序分发给其他用户和机器,你应该考虑制作一个分发包(见下面的附注3),并使用 package_data
来包含你的配置文件,使用 pkgutil
或 pkg_resources
来访问配置文件。查看如何从源代码中使用 package_data 的数据?
一些附注:
- 用带斜杠的目录名来表示目录,像
tree
命令的约定那样:用/
代替<root>
,用moduleOne/
代替<moduleOne>
- 你把“模块”和“包”搞混了。我建议你把
moduleOne/
改名为packageOne/
。一个包含__init__.py
文件的目录就是一个包。以.py
结尾的文件是模块。模块可以通过物理存在于包含__init__.py
文件的目录中成为包的一部分。包可以通过作为包含__init__.py
文件的父目录的物理子目录成为其他包的一部分。 - 不幸的是,在 Python 中“包”这个词有很多含义,它也可以指用于分发和安装的 Python 代码集合。查看Python 打包指南词汇表。