【问题标题】:system vs call vs popen in PythonPython中的系统vs调用vs popen
【发布时间】:2018-02-09 16:08:07
【问题描述】:
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

实际代码sn-p:

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)

【问题讨论】:

  • “不起作用”到底是什么意思?如果有错误消息,您需要发布它。
  • 没有错误信息。它悄悄地进入下一行代码
  • 还将call 替换为check_call 并报告结果。我很难相信这一点,没有冒犯
  • '{}'.format(images_dir+'/'+photo_name) 呸! => os.path.join(images_dir,photo_name)
  • check_call 就像call 一样安静地完成,对文件日期没有影响。

标签: python subprocess system-calls


【解决方案1】:

我根本不会为此使用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 的日期/时间参数必须是整数 UNIX 时间戳;您需要先将您的 date_in 值从它当前的值转换为第一值。

【讨论】:

  • 1. 为什么? 2.os.utime 内的with 块不会导致此代码中的原始问题吗?
  • 1.如果可能,最好避免分叉新进程。 2. 大概;无论如何都没有令人信服的理由让它在里面。
【解决方案2】:

现在很清楚了:

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

【讨论】:

  • 啊.. with 块。谢谢你修复它!
猜你喜欢
  • 2013-11-27
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
  • 1970-01-01
  • 2014-10-07
  • 2014-12-30
  • 1970-01-01
  • 2020-01-04
相关资源
最近更新 更多