Python 中的系统 vs 调用 vs popen

system vs call vs popen in Python

cmd = 'touch -d '+date_in+' '+images_dir+'/'+photo_name
os.system(cmd)

不起作用

subprocess.call(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])

不起作用

subprocess.Popen(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])

有效!

为什么?前两种情况我错过了什么?

pi@raspberrypi:~ $ python --version
Python 2.7.13

实际代码片段:

try:
    response = urllib2.urlopen(url)
    if(response.getcode() == 200):
        photo_file = response.read()
        with open(images_dir+'/'+photo_name,'wb') as output:
            output.write(photo_file)
            #cmd = 'touch -d '+date_in+' '+images_dir+'/'+photo_name
            #subprocess.Popen(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])
            subprocess.check_call(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])
        with open(images_dir+'/captions/'+photo_name+'.txt','wb') as output:
            output.write(photo_title)
    else:
        print 'Download error'
except Exception as message:
    print 'URL open exception {}'.format(message)

现在清楚了:

with open(images_dir+'/'+photo_name,'wb') as output:
    output.write(photo_file)
    #cmd = 'touch -d '+date_in+' '+images_dir+'/'+photo_name
    #subprocess.Popen(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])
    subprocess.check_call(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])

我的假设是:您仍在 with 块中,因此如果执行 check_callsystem,它将结束,然后关闭文件,设置日期再次破坏 touch 努力。

使用Popen,进程是在后台执行的,所以当它执行时,文件已经关闭(好吧,实际上它是一个竞争条件,不能保证)

我建议:

with open(images_dir+'/'+photo_name,'wb') as output:
    output.write(photo_file)
subprocess.check_call(['touch','-d','{}'.format(date_in),'{}'.format(images_dir+'/'+photo_name)])

因此当您调用 check_call

时文件会正确关闭

写得更好:

fullpath = os.path.join(images_dir,photo_name)
with open(fullpath ,'wb') as output:
    output.write(photo_file)
# we're outside the with block, note the de-indentation
subprocess.check_call(['touch','-d','{}'.format(date_in),fullpath])

我根本不会为此使用 touch;请改用 os.utime

import os

try:
    response = urllib2.urlopen(url)
except Exception as message:
    print 'URL open exception {}'.format(message)
else:
    if response.getcode() == 200:
        photo_file = response.read()
        f = os.path.join(images_dir, photo_name)
        with open(f,'wb') as output:
            output.write(photo_file)
        os.utime(f, (date_in, date_in))

        f = os.path.join(images_dir, 'captions', photo_name + '.txt')    
        with open(f, 'wb') as output:
            output.write(photo_title)
    else:
        print 'Download error'

请注意 os.utime 的 date/time 参数必须是整数 UNIX 时间戳;您需要首先将 date_in 值从当前的值转换。