简体   繁体   English

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

[英]Python: Program will not run in other directory

I am running ubuntu 12.04 and running programs through the terminal. 我正在运行ubuntu 12.04,并通过终端运行程序。 I have a file that compiles and runs without any issues when I am in the current directory. 当我在当前目录中时,我有一个可以编译并运行的文件,没有任何问题。 Example below, 下面的例子

    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$

Now when I go back one directory and try running the same piece of code, I get an error message, ValueError: need more than 1 value to unpack . 现在,当我返回一个目录并尝试运行同一段代码时,我收到一条错误消息ValueError: need more than 1 value to unpack Below is what happens when I run the sample code one folder back and then the sample code below that. 下面是当我将示例代码运行到一个文件夹然后在其下运行示例代码时发生的情况。

    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

The code, bill.py , below. 下面的代码bill.py This program reads two text files from the folder that it is located in and parses the lines into variables. 该程序从其所在的文件夹中读取两个文本文件,并将行解析为变量。

#!/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

What is going on here? 这里发生了什么? Am I not running the compile and run command in the terminal correctly? 我是否无法在终端中正确运行compile and run命令? Another note to know is that I eventually call this code from another file and it will not run the for loop, I am assuming since it doesn't run unless its called from its own folder/directory? 要知道的另一个注意事项是,我最终会从另一个文件调用此代码,因此我不会运行for循环,因为除非从自己的文件夹/目录中调用它,否则它不会运行?

Your problem starts in line 5: 您的问题从第5行开始:

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

You are telling glob to look in the local directory for all .txt files. 您要告诉glob在本地目录中查找所有.txt文件。 Since you are one directory up you do not have these files. 由于您位于一个目录中,因此没有这些文件。

You are getting a ValueError because the line variable is empty. 因为行变量为空,所以出现ValueError。

As it is written you will need to run it from that directory. 在编写时,您将需要从该目录运行它。

Edit: The way I see it you have three separate options. 编辑:我认为它有三个单独的选项。

  1. You could simply run script with the full path (assuming it is executable) 您可以简单地使用完整路径运行脚本(假设它是可执行文件)

    ~/Documents/BudgetAutomation/BillList/bill.py 〜/文档/ BudgetAutomation / BillList / bill.py

  2. You could put the full path into the file (although not very Pythonic) 您可以将完整路径放入文件中(尽管不是很Pythonic)

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

  3. You could use sys.argv to pass the path in the file. 您可以使用sys.argv在文件中传递路径。 This would be my personal preferred way. 这将是我个人的首选方式。 Use os.path.join to put the correct slashes. 使用os.path.join放置正确的斜杠。

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

As eomer explains , the problem is that './*.txt' is a relative path—relative to the current working directory. 正如eomer所解释的那样 ,问题在于'./*.txt'是相对于当前工作目录的相对路径。 If you're not running from the directory that all those *.txt files are in, you won't find anything. 如果您不是从所有这些*.txt文件所在的目录中运行,则将找不到任何内容。

If the *.txt files are supposed to be in the same directory as the script , use the same directory as the script , not the current working directory . 如果*.txt文件应该与脚本 位于同一目录中 ,请使用 脚本 相同的目录 ,而不是当前工作目录

The standard way of doing that is to put code like this at the top of your script: 这样做的标准方法是将这样的代码放在脚本的顶部:

import os
import sys

scriptdir = os.path.abspath(os.path.dirname(sys.argv[0]))
  • argv[0] gets the path to the script itself. argv[0]获取脚本本身的路径。 So, if you ran the script as python BillList/bill.py , this will be 'BillList/bill.py' . 因此,如果您以python BillList/bill.py身份运行脚本,则该脚本将为'BillList/bill.py' * *

  • dirname just takes a path to a file, and gives you the path to the directory the file was in. So, in this case, BillList . dirname只是获取文件的路径,并为您提供文件所在目录的路径。因此,在这种情况下,为BillList

  • abspath normalizes and absolutizes the path. abspath规范化和绝对化路径。 ** So, you'll get /home/david/Documents/BudgetAutomation/BillList/ . **因此,您将获得/home/david/Documents/BudgetAutomation/BillList/ And that's the directory the *.txt files are in. 这就是*.txt文件所在的目录。

Then, instead of this: 然后,代替此:

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

… you do this: … 你做这个:

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

* Actually, on some platforms you will get an absolute path here, rather than relative, meaning the later abspath is unnecessary. *事实上,在某些平台上,你会在这里得到一个绝对路径,而不是相对的,这意味着以后abspath是不必要的。 But for portability, it's worth doing. 但是对于可移植性,这是值得做的。 A bigger problem is that in some cases you will get just bill.py , with no path. 一个更大的问题是,在某些情况下,您只会得到bill.py ,没有路径。 There used to be cases where it was worth checking for that and trying __file__ instead, but as far as I know that isn't true on any modern platform—and there are cases where __file__ is wrong but argv[0] is right. 过去,有一些值得检查并尝试使用__file__ ,但据我所知,在任何现代平台上都不是这样-有时__file__是错误的,但argv[0]是正确的。

** For a relative path, it absolutizes it relative to the current working directory. **对于相对路径,它相对于当前工作目录而言是绝对的。 That's why it's important to do this at the top of the script—in case someone does an os.chdir later. 这就是为什么在脚本顶部执行此操作很重要,以防os.chdir以后有人执行os.chdir

You don't need to create that range object to iterate over the glob result. 您无需创建该范围对象即可遍历全局结果。 You can just do it like this: 您可以这样做:

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

The reason of why that exception is raised, I guess, is there exist text files contain content not conforming with your need. 我猜为什么会出现该异常,是因为存在文本文件包含不符合您需求的内容。 You read a line from that file, which is something may be like "foo|bar", then the splitting result of it is ["foo", "bar"]. 您从该文件中读取了一行,可能类似于“ foo | bar”,然后拆分结果为[“ foo”,“ bar”]。

If you want to avoid this exception, you could just catch it: 如果要避免此异常,可以捕获它:

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

You must use absolute path arr = glob.glob('./*.txt') here. 您必须在此处使用绝对路径arr = glob.glob('./*.txt')

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

If possible use below code 如果可能,请使用以下代码

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

This will provide you with list of files that you want to glob with 这将为您提供您想要的文件列表glob

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM