Вот решение Alex Martelli как модуль с надлежащим убийством процесса. Другие подходы не работают, потому что они не используют proc.communicate (). Поэтому, если у вас есть процесс, который производит много результатов, он заполнит свой выходной буфер, а затем заблокирует, пока вы не прочитаете что-нибудь из него.
from os import kill
from signal import alarm, signal, SIGALRM, SIGKILL
from subprocess import PIPE, Popen
def run(args, cwd = None, shell = False, kill_tree = True, timeout = -1, env = None):
'''
Run a command with a timeout after which it will be forcibly
killed.
'''
class Alarm(Exception):
pass
def alarm_handler(signum, frame):
raise Alarm
p = Popen(args, shell = shell, cwd = cwd, stdout = PIPE, stderr = PIPE, env = env)
if timeout != -1:
signal(SIGALRM, alarm_handler)
alarm(timeout)
try:
stdout, stderr = p.communicate()
if timeout != -1:
alarm(0)
except Alarm:
pids = [p.pid]
if kill_tree:
pids.extend(get_process_children(p.pid))
for pid in pids:
# process might have died before getting to this line
# so wrap to avoid OSError: no such process
try:
kill(pid, SIGKILL)
except OSError:
pass
return -9, '', ''
return p.returncode, stdout, stderr
def get_process_children(pid):
p = Popen('ps --no-headers -o pid --ppid %d' % pid, shell = True,
stdout = PIPE, stderr = PIPE)
stdout, stderr = p.communicate()
return [int(p) for p in stdout.split()]
if __name__ == '__main__':
print run('find /', shell = True, timeout = 3)
print run('find', shell = True)
Это возможное решение, и оно сработало для меня.
Вместо создания новой политики вы можете также взять существующую политику из хранилища больших двоичных объектов. см. https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1
private Uri GetDownloadUri(CloudBlockBlob blob)
{
try
{
// Return the SAS token.
var query = GenerateSASQueryString(blob);
UriBuilder newUri = new UriBuilder(blob.Uri)
{
Query = query
};
return newUri.Uri;
}
catch (UriFormatException ex)
{
Console.WriteLine(ex);
}
return blob.Uri;
}
private string GenerateSASQueryString(CloudBlockBlob blob)
{
if (blob == null)
return null;
// Create a new access policy for the account.
SharedAccessBlobPolicy policy = new SharedAccessBlobPolicy
{
Permissions = SharedAccessBlobPermissions.Read,
SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddHours(24),
SharedAccessStartTime = DateTimeOffset.UtcNow
};
// Return the SAS token.
var query = blob.GetSharedAccessSignature(policy);
return query;
}