【问题标题】:cannot concatenate 'str' and 'file' objects : Python error无法连接“str”和“file”对象:Python 错误
【发布时间】:2015-07-09 23:02:00
【问题描述】:

我有

以下代码:

for src_filename, src_code in src_dict.iteritems(): 
try:
set.dependencies = subprocess.check_output('unifdef -s /home/c/maindir/folder/' +src_filename, shell=True)
except subprocess.CalledProcessError, e:
       print "code is bad" +set.property
       set.bad = 1
       raise
set.dependencies = list(set(set.dependencies.splitlines()))

我想取消对路径的硬编码 所以我写了以下代码:

filepath = os.path.join(maindirpath, "folder/")

maindir 是这里的参数:/home/c/maindir

 path = open(filepath)
 set.dependencies = subprocess.check_output("unifdef" '-s' path +src_filename, shell=True)

它会抛出以下错误:

TypeError: cannot concatenate 'str' and 'file' objects

我是 python 新手。任何人都可以帮忙,我哪里出错了?

【问题讨论】:

  • 很明显,src_filename 是一个文件对象,而不是文件名,尽管它的名称误导性地声称并非如此。
  • 另外,shell=True 是邪恶的,因此您的代码存在安全漏洞(看看如果 src_filename"hello $(rm -rf .).txt" 会发生什么。
  • 顺便说一下,值得注意的是,您展示了您是如何获得filepathpath,而不是src_filename,这是您实际使用的论点。请在将来检查您的代码是否可以复制和粘贴以重现您所询问的问题,而无需事先设置。另见:sscce.org
  • 基本上我想保持代码不变,只是想使用'path'而不是硬编码路径。
  • path 是一个文件。要获取文件名,请使用path.name,

标签: python


【解决方案1】:
for src_file, src_code in src_dict.iteritems():

  # assuming, here, that you want to honor the handle's path if already given
  filename = src_file.name
  if not '/' in filename:
    filename = os.path.join(filepath, filename)

  try:
    set.dependencies = subprocess.check_output(['unifdef', '-s', filename])
  except subprocess.CalledProcessError:
    pass # etc.

顺便说一句,set 是一个错误的变量名,因为set 也是 Python 数据类型;您通过使用同名变量对其进行隐藏,从而使数据类型在您的代码中不可用。不要那样做!

【讨论】:

  • 你有一个文件对象。对象所支持的文件已在其名称中包含路径,除非您尝试引用不同目录中的同名文件。
  • 在“引用不同目录中的同名文件”的情况下,使用 sancho.s 建议的 basename() 方法——但理想情况下,将它与给定的子进程使用模式结合起来在这里,您使用shell=True
  • 耸耸肩。我无法重现您的错误,因此该报告对任何人都没有任何好处。如果您的代码是适当的 SSCCE(尤其是自包含),我们可以测试我们的实现并知道它们做了什么或没做什么,但是您在这里的问题描述得不够有用,无法让任何人都可以测试他们的答案。
【解决方案2】:

我想我明白了,我会尝试以下方法:

import os

D = os.getcwd()           # returns a string
newD = (D + '/folder/')   # concatenates the two strings together

我一直都在使用它,如果 os.getcwd()(获取当前工作目录)不是您想要的,在 os 模块下有类似的选项也会返回一个字符串。我相信您知道,在 IDLE 中输入 help(os) 应该会显示所有选项。

【讨论】:

    【解决方案3】:

    您正在尝试连接 'unifdef -s /home/c/maindir/folder/'src_filename 第一个是字符串,所以第二个可能是文件对象。

    根据您编辑的版本,您可能需要

    bytestr = subprocess.check_output( [ 'unifdef', '-s', filepath + os.path.basename(src_filename.name) ] )
    

    而不是

    set.dependencies = subprocess.check_output("unifdef" '-s' path +src_filename, shell=True)
    

    (记住subprocess.check_outputreturns a byte string)。 然后将bytestr 分配给您需要的任何内容。

    你甚至可能想要

    try :
        bytestr = subprocess.check_output( [ 'unifdef', '-s', filepath + os.path.basename(src_filename.name) ], stderr=subprocess.STDOUT )
    except subprocess.CalledProcessError :
        ...
    

    这可能有效,尽管它非常初级,并且您可能有更好的选项可用于您的其余代码(我们不知道)。

    How do you use subprocess.check_output() in Python?

    【讨论】:

    • 确实如此。如何重新排列代码,而不是硬编码路径。它将采用路径并将其与 src_filename 连接起来
    • @geek_xed,我们怎么能告诉你如何重新排列你一开始没有给我们的代码?根据stackoverflow.com/help/mcve 的规则,您的问题需要包含重现问题的代码
    • 代码很大。我不能复制粘贴。我只在该声明中收到错误。我不确定如何使用路径。
    • @geek_xed,我为您提供的 MCVE 和 SSCCE 链接向您展示了如何将一大段代码分解为最小的复制器。这是工作,但是,您要求我们为您工作;你也做一些工作是公平的。 :)
    • @sancho.s,更好,但是当我们不知道该名称将解析回自身时,我们真的想鼓励某人将src_filename.name 传递给外壳吗?想想如果名称包含空格会发生什么。使用pipes.quote 或它的Python 3 shlex.quote 替换会更少错误,但最好修改代码以不使用shell=True
    猜你喜欢
    • 1970-01-01
    • 2014-08-19
    • 2017-10-13
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多