Вы забыли фактическую часть JSON - data
- это словарь и еще не закодированный JSON. Напишите это следующим образом:
import json
with open('data.json', 'w') as outfile:
json.dump(data, outfile)
Примечание: Работает как с 3.x, так и с 2.x.
Существует только обходной путь для проблемы, с которой вы сталкиваетесь.
Перед запуском процесса копирования проверьте, не запущен ли файл. Вы можете вызвать следующую функцию, пока не получите значение False.
1st Method, скопированный непосредственно из этого ответа :
private bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
2nd Method:
const int ERROR_SHARING_VIOLATION = 32;
const int ERROR_LOCK_VIOLATION = 33;
private bool IsFileLocked(string file)
{
//check that problem is not in destination file
if (File.Exists(file) == true)
{
FileStream stream = null;
try
{
stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (Exception ex2)
{
//_log.WriteLog(ex2, "Error in checking whether file is locked " + file);
int errorCode = Marshal.GetHRForException(ex2) & ((1 << 16) - 1);
if ((ex2 is IOException) && (errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION))
{
return true;
}
}
finally
{
if (stream != null)
stream.Close();
}
}
return false;
}
Итак, быстро просмотрев некоторые из этих и других подобных вопросов, я отправился на веселой гусиной погоне сегодня днем, пытаясь решить проблему с двумя отдельными программами, используя файл в качестве метода синхронизации (а также сохранения файла). Немного необычная ситуация, но это определенно выделило для меня проблемы с «проверкой, заблокирован ли файл, а затем откройте его, если он не подходит».
Проблема заключается в следующем: файл может стать заблокировано между временем, которое вы проверяете, и временем, когда вы действительно открываете файл. Его действительно сложно отследить спорадический. Невозможно скопировать файл, потому что он используется другой технологической ошибкой, если вы ее тоже не ищете.
Основное разрешение - просто попытаться открыть файл внутри блок блокировки, чтобы, если он заблокирован, вы можете попробовать еще раз. Таким образом, между проверкой и открытием нет времени, операционная система делает это одновременно.
В этом коде используется File.Copy, но он работает точно также с любым из статических методов класса File: File.Open, File.ReadAllText, File.WriteAllText и т. д.
/// <param name="timeout">how long to keep trying in milliseconds</param>
static void safeCopy(string src, string dst, int timeout)
{
while (timeout > 0)
{
try
{
File.Copy(src, dst);
//don't forget to either return from the function or break out fo the while loop
break;
}
catch (IOException)
{
//you could do the sleep in here, but its probably a good idea to exit the error handler as soon as possible
}
Thread.Sleep(100);
//if its a very long wait this will acumulate very small errors.
//For most things it's probably fine, but if you need precision over a long time span, consider
// using some sort of timer or DateTime.Now as a better alternative
timeout -= 100;
}
}
Еще одна небольшая заметка о parellelism: Это синхронный метод, который будет блокировать поток как во время ожидания, так и при работе над потоком. Это самый простой подход, но если файл остается заблокированным в течение длительного времени, ваша программа может перестать отвечать на запросы. Parellelism - слишком большая тема для углубленного изучения здесь (и количество способов, которые вы могли бы настроить асинхронным чтением / записью, является нелепым), но вот один из способов, которым это может быть parellelized.
public class FileEx
{
public static async void CopyWaitAsync(string src, string dst, int timeout, Action doWhenDone)
{
while (timeout > 0)
{
try
{
File.Copy(src, dst);
doWhenDone();
break;
}
catch (IOException) { }
await Task.Delay(100);
timeout -= 100;
}
}
public static async Task<string> ReadAllTextWaitAsync(string filePath, int timeout)
{
while (timeout > 0)
{
try {
return File.ReadAllText(filePath);
}
catch (IOException) { }
await Task.Delay(100);
timeout -= 100;
}
return "";
}
public static async void WriteAllTextWaitAsync(string filePath, string contents, int timeout)
{
while (timeout > 0)
{
try
{
File.WriteAllText(filePath, contents);
return;
}
catch (IOException) { }
await Task.Delay(100);
timeout -= 100;
}
}
}
И вот как это можно использовать:
public static void Main()
{
test_FileEx();
Console.WriteLine("Me First!");
}
public static async void test_FileEx()
{
await Task.Delay(1);
//you can do this, but it gives a compiler warning because it can potentially return immediately without finishing the copy
//As a side note, if the file is not locked this will not return until the copy operation completes. Async functions run synchronously
//until the first 'await'. See the documentation for async: https://msdn.microsoft.com/en-us/library/hh156513.aspx
CopyWaitAsync("file1.txt", "file1.bat", 1000);
//this is the normal way of using this kind of async function. Execution of the following lines will always occur AFTER the copy finishes
await CopyWaitAsync("file1.txt", "file1.readme", 1000);
Console.WriteLine("file1.txt copied to file1.readme");
//The following line doesn't cause a compiler error, but it doesn't make any sense either.
ReadAllTextWaitAsync("file1.readme", 1000);
//To get the return value of the function, you have to use this function with the await keyword
string text = await ReadAllTextWaitAsync("file1.readme", 1000);
Console.WriteLine("file1.readme says: " + text);
}
//Output:
//Me First!
//file1.txt copied to file1.readme
//file1.readme says: Text to be duplicated!
Ну, вы уже сами дали ответ; вам нужно дождаться завершения создания файла. Один из способов сделать это - проверить, сохраняется ли файл. Пример этого можно найти здесь: Есть ли способ проверить, используется ли файл?
Обратите внимание, что вам придется изменить этот код, чтобы он работал в ваша ситуация. Возможно, вы захотите иметь что-то вроде (псевдокода):
public static void listener_Created()
{
while CheckFileInUse()
wait 1000 milliseconds
CopyFile()
}
Очевидно, что вы должны защитить себя от бесконечного while
, если приложение владельца никогда не освобождает блокировку. Кроме того, возможно, стоит проверить другие события из FileSystemWatcher
, на которые вы можете подписаться. Может быть событие, которое вы можете использовать, чтобы обойти эту проблему.
Я хотел бы добавить здесь ответ, потому что это сработало для меня. Я использовал задержки времени, в то время как циклы, все, что я мог придумать.
У меня было окно Windows Explorer открытой папки вывода. Я закрыл его, и все работало как прелесть.
Надеюсь, это кому-то поможет.
Это старый поток, но я добавлю некоторую информацию для других людей.
У меня возникла аналогичная проблема с программой, которая пишет файлы PDF, иногда они занимают 30 секунд для рендеринга. тот же период, в течение которого мой класс watcher_FileCreated ждет перед копированием файла.
Файлы не были заблокированы.
В этом случае я проверил размер PDF-файла, а затем ждал 2 секунды перед сравнением новый размер, если они были неравными, нить будет спать в течение 30 секунд и повторить попытку.
Вы можете использовать следующий код, чтобы проверить, может ли файл быть открыт с эксклюзивным доступом (то есть он не открывается другим приложением). Если файл не закрыт, вы можете подождать несколько секунд и снова проверить, пока файл не будет закрыт, и вы можете его скопировать.
Вы все равно должны проверить, не сработал ли File.Copy, поскольку другое приложение может откройте файл с момента проверки файла и момента его копирования.
public static bool IsFileClosed(string filename)
{
try
{
using (var inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
{
return true;
}
}
catch (IOException)
{
return false;
}
}
Когда файл записывается в двоичном формате (байт by byte), создайте FileStream и выше решения Не работает, потому что файл готов и wrotted в каждом байте, поэтому в этой ситуации вам нужно другое обходное решение, подобное этому: сделайте это при создании файла или вы хотите начать обработку в файле
long fileSize = 0;
currentFile = new FileInfo(path);
while (fileSize < currentFile.Length)//check size is stable or increased
{
fileSize = currentFile.Length;//get current size
System.Threading.Thread.Sleep(500);//wait a moment for processing copy
currentFile.Refresh();//refresh length value
}
//Now file is ready for any process!
Из документации для FileSystemWatcher
:
Событие
blockquote>OnCreated
возникает, как только создается файл. Если файл копируется или переносится в наблюдаемый каталог, событиеOnCreated
будет немедленно поднято, за которым следуют один или несколько событийOnChanged
.Итак, если копия не выполнена , (поймайте исключение), добавьте его в список файлов, которые все еще нужно переместить, и попытайтесь выполнить копию во время события
OnChanged
. В конце концов, он должен работать.Что-то вроде (неполное, улавливать определенные исключения, инициализировать переменные и т. Д.):
public static void listener_Created(object sender, FileSystemEventArgs e) { Console.WriteLine ( "File Created:\n" + "ChangeType: " + e.ChangeType + "\nName: " + e.Name + "\nFullPath: " + e.FullPath ); try { File.Copy(e.FullPath, @"D:\levani\FolderListenerTest\CopiedFilesFolder\" + e.Name); } catch { _waitingForClose.Add(e.FullPath); } Console.Read(); } public static void listener_Changed(object sender, FileSystemEventArgs e) { if (_waitingForClose.Contains(e.FullPath)) { try { File.Copy(...); _waitingForClose.Remove(e.FullPath); } catch {} } }
На самом деле вам повезло - программа, записывающая файл, блокирует его, поэтому вы не можете его открыть. Если он не заблокировал его, вы скопировали бы частичный файл, не имея никакой идеи, что есть проблема.
Когда вы не можете получить доступ к файлу, вы можете предположить, что он все еще используется (еще лучше - попробуйте открыть его в эксклюзивном режиме и посмотрите, не открывает ли кто-нибудь еще его, вместо того, чтобы угадывать из-за отказа File.Copy). Если файл заблокирован, вам придется скопировать его в другое время. Если он не заблокирован, вы можете скопировать его (здесь есть небольшой потенциал для состояния гонки).
Когда это «другое время»? Я не помню, когда FileSystemWatcher отправляет несколько событий на файл - проверьте это, вам может быть достаточно просто проигнорировать событие и ждать другого. Если нет, вы всегда можете настроить время и перепроверять файл за 5 секунд.
ERROR_SHARING_VIOLATION
= 32,ERROR_LOCK_VIOLATION
= 33) – Julien N 17 May 2016 в 16:52