Python: 程序不会在其他目录下运行

Python: Program will not run in other directory

我正在通过终端 运行ning ubuntu 12.04 和 运行ning 程序。当我在当前目录中时,我有一个编译和 运行s 没有任何问题的文件。下面的示例,

    david@block-ubuntu:~/Documents/BudgetAutomation/BillList$ pwd
    /home/david/Documents/BudgetAutomation/BillList
    david@block-ubuntu:~/Documents/BudgetAutomation/BillList$ python3.4 bill.py
    ./otherlisted.txt
    ./monthlisted.txt
    david@block-ubuntu:~/Documents/BudgetAutomation/BillList$

现在,当我返回一个目录并尝试 运行使用同一段代码时,我收到一条错误消息 ValueError: need more than 1 value to unpack。下面是当我 运行 将示例代码返回一个文件夹,然后是下面的示例代码时发生的情况。

    david@block-ubuntu:~/Documents/BudgetAutomation$ python3.4 /home/david/Documents/BudgetAutomation/BillList/bill.py 
    Traceback (most recent call last):
    File "/home/david/Documents/BudgetAutomation/BillList/bill.py", line 22, in <module>
        bill_no, bill_name, trash = line.split('|', 2)
    ValueError: need more than 1 value to unpack

下面的代码 bill.py。该程序从它所在的文件夹中读取两个文本文件,并将这些行解析为变量。

#!/usr/bin/env python
import glob

# gather all txt files in directory
arr = glob.glob('./*.txt')
arrlen = int(len(arr))

# create array to store list of bill numbers and names
list_num = []
list_name = []

# for loop that parses lines into appropriate variables
for i in range(arrlen):
    with open(arr[i]) as input:
        w = 0 ## iterative variable for arrays
        for line in input:
            list_num.append(1) ## initialize arrays
            list_name.append(1)

            # split line into variables.. trash is rest of line that has no use
            bill_no, bill_name, trash = line.split('|', 2)

            # stores values in array
            list_num[w] = bill_no
            list_name[w] = bill_name

            w += 1

这是怎么回事?我在终端中 运行 编译和 运行 命令是否正确?另一个要知道的注意事项是我最终从另一个文件调用此代码并且它不会 运行 for 循环,我假设它不会 运行 除非它从它自己的 folder/directory?

您的问题从第 5 行开始:

arr = glob.glob('./*.txt')

您要让 glob 在本地目录中查找所有 .txt 文件。由于您在上一级目录中,因此您没有这些文件。

您收到 ValueError,因为行变量为空。

如上所示,您需要从该目录中运行它。

编辑: 在我看来,您有三个不同的选择。

  1. 您可以简单地 运行 带有完整路径的脚本(假设它是可执行的)

    ~/Documents/BudgetAutomation/BillList/bill.py

  2. 您可以将完整路径放入文件中(虽然不是很 Pythonic)

    arr = glob.glob('/home/[用户名]/Documents/BudgetAutomation/BillList/*.txt')

  3. 您可以使用sys.argv来传递文件中的路径。这将是我个人的首选方式。使用 os.path.join 放置正确的斜杠。

    arr = glob.glob(os.path.join(sys.argv1, '*.txt'))

您不需要创建范围对象来迭代 glob 结果。你可以这样做:

for file_path in arr:
    with open(file_path) as text_file:
        #...code below...

之所以会出现这个异常,我猜想是存在文本文件包含不符合您需要的内容。你从那个文件中读取一行,可能是"foo|bar",那么它的拆分结果是["foo","bar"]。

如果你想避免这个异常,你可以直接捕获它:

try:
    bill_no, bill_name, trash = line.split('|', 2)
except ValueError:
    # You can do something more meaningful but just "pass"
    pass

此处必须使用绝对路径arr = glob.glob('./*.txt')

做类似arr = glob.glob('/home/abc/stack_overflow/*.txt')

的事情

如果可能使用下面的代码

dir_name = "your directory name" # /home/abc/stack_overflow
[file for file in os.listdir(dir_name) if file.endswith('txt')]

这将为您提供您想要glob

的文件列表

一样,问题在于'./*.txt'是相对路径——相对于当前工作目录。如果您不在所有这些 *.txt 文件所在的目录中 运行,您将找不到任何东西。

如果 *.txt 文件应该与脚本在同一目录中,请使用与脚本[=66]相同的目录=],而不是当前工作目录

这样做的标准方法是将这样的代码放在脚本的顶部:

import os
import sys

scriptdir = os.path.abspath(os.path.dirname(sys.argv[0]))
  • argv[0] 获取脚本本身的路径。所以,如果你 运行 脚本为 python BillList/bill.py,这将是 'BillList/bill.py'.*

  • dirname 只是获取一个文件的路径,并为您提供文件所在目录的路径。因此,在这种情况下,BillList.

  • abspath 标准化和绝对化路径。** 所以,你会得到 /home/david/Documents/BudgetAutomation/BillList/。这就是 *.txt 文件所在的目录。

然后,代替这个:

glob.glob('./*.txt')

……你这样做:

glob.glob(os.path.join(scriptdir, '*.txt'))

* 实际上,在某些平台上,您会在此处获得绝对路径,而不是相对路径,这意味着后面的 abspath 是不必要的。但为了便携性,这是值得做的。一个更大的问题是,在某些情况下,您只会得到 bill.py,而没有路径。过去在某些情况下值得检查并尝试 __file__,但据我所知,在任何现代平台上都不是这样——在某些情况下 __file__ 是错误的,但argv[0]是对的。

** 对于相对路径,相对于当前工作目录绝对化。这就是为什么在脚本顶部执行此操作很重要 - 以防有人稍后执行 os.chdir