system vs call vs popen in Python

笑着哭i 提交于 2019-12-11 10:11:02

问题


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

Doesn't work

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

Doesn't work

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

Works!

Why? What am I missing in first two cases?

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

Actual code snippet:

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)

回答1:


Now it's clear:

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)])

My assumption is: you're still in the with block, so if check_call or system is performed, it ends, then the file is closed, setting the date again and ruining touch efforts.

With Popen, the process is performed in the background, so when it's executed, the file is already closed (well, actually it's a race condition, it's not guaranteed)

I suggest:

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)])

so the file is properly closed when you call check_call

Better written:

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])



回答2:


I wouldn't use touch at all for this; use os.utime instead.

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'

Note that the date/time arguments to os.utime must be integer UNIX timestamps; you'll need to convert your date_in value from whatever it currently is first.



来源:https://stackoverflow.com/questions/48709793/system-vs-call-vs-popen-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!