将使用 Python 的临时文件创建的临时文件传递给忽略行结束首选项的命令行程序

Passing a temporary file created with Python's tempfile to a command line program ignoring line ending preferences

我为此苦苦思索了 16 个小时,但我似乎找不到任何人遇到完全相同的问题。

我有一个命令行程序(我将称之为 CLI)我正在使用它,它以一个文本文件作为参数,其中文件的每一行都有重要信息。无需详细说明,CLI 会将文件的行传递给完成某些操作的 Web 服务。

我有一个正在编写的 python 程序,我在其中创建以编程方式(使用子进程)传递给 CLI 的文件。问题似乎是 web 服务在某个地方收到了一个不知道如何处理的回车 return。在创建进入该文件的每一行时,我非常小心地避免了任何回车符 returns,但显然回车符 returns 被添加到末尾。我以二进制模式打开我的文件,果然,有回车return。无赖。

没关系,我一直看到这里共享的脚本展示了如何将文件从 CRLF 转换为 LF。将那几行添加到我的 python 脚本中,并仔细检查,果然,当以二进制模式读取文件时,回车 return 不见了。万岁。

但是当我再次转到 运行 脚本时,由于某种原因,Web 服务仍在接收回车 returns。

我怀疑它与我正在使用的 python 临时文件系统有关。也许它在幕后以某种奇怪的方式工作,在我将文件更改为使用 LF 并打印其内容之后,在某些时候它会将其更改回来(也许当它作为参数传递给 CLI 时)

我想我的问题是 1) 你能想到 tempfile 可能会做些什么来弄乱我的文件结尾,即使看起来我已经改变了它们吗?也许当临时文件通过子进程以某种方式恢复到 cli 时?我只是用 temp.name.

发送

或者 2) 也许我可以做一些 python 内置临时文件以外的事情。它真的很方便,所以如果我不打算使用它,是否有一些我应该了解的手动创建和删除临时文件的最佳实践?有没有最好的地方来创建它们?例如,在当前目录下创建然后删除文件是否被认为是不好的做法?

无论如何,这是更改行尾后我的代码的相关部分:

def my_function(mylist, my_id, local_id, args):
    temp = tempfile.NamedTemporaryFile(mode='w+b', delete=False)
    for each in mylist:
        is_directory = False
        destination = args.destination.replace("\", "/")
        if each["smallpath"] == "/":
            full_path = each["smallpath"] + "/"
        else:
            full_path = each["rel_path"].replace("\", "/") + "/" + each["specific_path"].lstrip("/")
        if os.path.basename(full_path) == "":
            is_directory = True
        if is_directory is False:
            line = f'"{full_path}" "~/{destination}/{each["orgID"]}-{each["userID"]}/{os.path.basename(full_path)}" \n'
        else:
            if each["smallpath"] != "/":
                slash_index = full_path.rstrip('/').rfind("/")
                local_dir = full_path[slash_index:].rstrip().rstrip('/')
            else:
                local_dir = "/"
            line = f'"{full_path}" "~/{destination}/{each["orgID"]}-{each["userID"]}/{local_dir.lstrip("/")}" --recursive \n'
        line = line.replace("\", "/")
        temp.write(line)
    temp.seek(0)
    windows_ending = b'\r'
    unix_ending = b'\n'
    double_newline = b'\n\n'
    with open(temp.name, 'rb') as file:
        file_contents = file.read()
    temp.seek(0)
    file_contents = file_contents.replace(windows_ending, unix_ending)
    file_contents = file_contents.replace(double_newline, unix_ending)
    with open(temp.name, 'wb') as file:
        file.write(file_contents)
    myprocess = subprocess.Popen(["programname", "commandname", myid, local_id, "--batch",
                                                temp.name], stdout=subprocess.PIPE)
    mycommand = myprocess.communicate()[0].decode('utf-8')
    temp.close()
    os.unlink(temp.name)

我想感谢所有试图提供帮助的人。这些评论帮助我在代码的其他地方发现了另一个漏洞。问题最终不是我自己的,而是我使用的服务