模块路径依赖

1 投票
1 回答
1760 浏览
提问于 2025-04-18 05:49

假设我们有一个项目的目录结构如下:

<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

你需要更多的抽象。

  1. 不要在 printfile.py 中直接写死文件路径。
  2. printf 函数中不要访问全局变量。
  3. 应该把文件句柄作为参数传给 printf 函数:

    def printf(file_handle):
        print 'print file'
        print file_handle
    
  4. 在一个确实需要知道 f.txt 路径的脚本中(我猜在你的例子中是 helloworld.py),把路径放在那儿,打开它,然后传给 printf

    from moduleOne.printfile import printf
    
    my_f_file = open('/path/to/f.txt')
    printf(my_f_file)
    
  5. 更好的是,从命令行获取文件路径:

    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 来包含你的配置文件,使用 pkgutilpkg_resources 来访问配置文件。查看如何从源代码中使用 package_data 的数据?

一些附注:

  1. 用带斜杠的目录名来表示目录,像 tree 命令的约定那样:用 / 代替 <root>,用 moduleOne/ 代替 <moduleOne>
  2. 你把“模块”和“包”搞混了。我建议你把 moduleOne/ 改名为 packageOne/。一个包含 __init__.py 文件的目录就是一个包。以 .py 结尾的文件是模块。模块可以通过物理存在于包含 __init__.py 文件的目录中成为包的一部分。包可以通过作为包含 __init__.py 文件的父目录的物理子目录成为其他包的一部分。
  3. 不幸的是,在 Python 中“包”这个词有很多含义,它也可以指用于分发和安装的 Python 代码集合。查看Python 打包指南词汇表

撰写回答