Если вы не инициализировали ссылочный тип и хотите установить или прочитать одно из его свойств, он будет генерировать исключение NullReferenceException.
Пример:
Person p = null;
p.Name = "Harry"; // NullReferenceException occurs here.
Вы можно просто избежать этого, проверив, является ли переменная не нулевой:
Person p = null;
if (p!=null)
{
p.Name = "Harry"; // Not going to run to this point
}
Чтобы полностью понять, почему выбрано исключение NullReferenceException, важно знать разницу между типами значений и ссылочные типы .
Итак, если вы имеете дело со типами значений, NullReferenceExceptions не может произойти. Хотя вам нужно поддерживать оповещение при работе со ссылочными типами!
Только ссылочные типы, как следует из названия, могут содержать ссылки или буквально буквально ничто (или «нуль»). Если типы значений всегда содержат значение.
Типы ссылок (эти должны быть проверены):
Типы значений (вы можете просто игнорировать эти):
Я думаю, что-то вроде этого должно это сделать. Он в основном записывает содержимое в новый файл и заменяет старый файл новым файлом:
from tempfile import mkstemp
from shutil import move
from os import fdopen, remove
def replace(file_path, pattern, subst):
#Create temp file
fh, abs_path = mkstemp()
with fdopen(fh,'w') as new_file:
with open(file_path) as old_file:
for line in old_file:
new_file.write(line.replace(pattern, subst))
#Remove original file
remove(file_path)
#Move new file
move(abs_path, file_path)
Для пользователей Linux:
import os
os.system('sed -i \'s/foo/bar/\' '+file_path)
Самый короткий путь, вероятно, будет заключаться в использовании fileinput module . Например, следующее добавляет номера строк в файл, на месте:
import fileinput
for line in fileinput.input("test.txt", inplace=True):
print "%d: %s" % (fileinput.filelineno(), line),
. Что происходит здесь:
print
записывают обратно в исходный файл fileinput
имеет больше колоколов и свистов. Например, он может использоваться для автоматической работы со всеми файлами в sys.args[1:]
, без необходимости явно перебирать их. Начиная с Python 3.2, он также предоставляет удобный менеджер контекста для использования в инструкции with
.
Хотя fileinput
отлично подходит для сценариев throwaway, я бы с осторожностью использовал его в реальном коде потому что, по общему признанию, это не очень читаемо или знакомо. В реальном (производственном) коде стоит потратить еще несколько строк кода, чтобы сделать процесс явным и, следовательно, сделать код читаемым.
Есть два варианта:
Используя ответ hamishmcn в качестве шаблона, я смог найти строку в файле, которая соответствует моему регулярному выражению и заменяет его пустой строкой.
import re
fin = open("in.txt", 'r') # in file
fout = open("out.txt", 'w') # out file
for line in fin:
p = re.compile('[-][0-9]*[.][0-9]*[,]|[-][0-9]*[,]') # pattern
newline = p.sub('',line) # replace matching strings with empty string
print newline
fout.write(newline)
fin.close()
fout.close()
Более питоновским способом будет использование контекстных менеджеров, таких как код ниже:
from tempfile import mkstemp
from shutil import move
from os import remove
def replace(source_file_path, pattern, substring):
fh, target_file_path = mkstemp()
with open(target_file_path, 'w') as target_file:
with open(source_file_path, 'r') as source_file:
for line in source_file:
target_file.write(line.replace(pattern, substring))
remove(source_file_path)
move(target_file_path, source_file_path)
Здесь вы можете найти полный фрагмент здесь .
Это должно работать: (редактирование на месте)
import fileinput
# Does a list of files, and
# redirects STDOUT to the file in question
for line in fileinput.input(files, inplace = 1):
print line.replace("foo", "bar"),
files
должна быть строкой, содержащей имя файла, не файл-объект .
– atomh33ls
30 August 2013 в 11:00
Как предлагает lassevk, напишите новый файл, как вы идете, вот пример кода:
fin = open("a.txt")
fout = open("b.txt", "wt")
for line in fin:
fout.write( line.replace('foo', 'bar') )
fin.close()
fout.close()
Расширение ответа @ Kiran, которое я согласен, более кратким и Pythonic, это добавляет кодеки для поддержки чтения и записи UTF-8:
import codecs
from tempfile import mkstemp
from shutil import move
from os import remove
def replace(source_file_path, pattern, substring):
fh, target_file_path = mkstemp()
with codecs.open(target_file_path, 'w', 'utf-8') as target_file:
with codecs.open(source_file_path, 'r', 'utf-8') as source_file:
for line in source_file:
target_file.write(line.replace(pattern, substring))
remove(source_file_path)
move(target_file_path, source_file_path)
Создайте новый файл, скопируйте строки из старого в новый и замените его перед тем, как писать строки в новый файл.
, если вы удалите отступ внизу, он будет искать и заменять в нескольких строках. См. Ниже, например.
def replace(file, pattern, subst):
#Create temp file
fh, abs_path = mkstemp()
print fh, abs_path
new_file = open(abs_path,'w')
old_file = open(file)
for line in old_file:
new_file.write(line.replace(pattern, subst))
#close temp file
new_file.close()
close(fh)
old_file.close()
#Remove original file
remove(file)
#Move new file
move(abs_path, file)
Если вам нужна общая функция, которая заменяет текст любой другим текстом, это, вероятно, лучший способ, особенно если вы поклонник регулярных выражений:
import re
def replace( filePath, text, subs, flags=0 ):
with open( filePath, "r+" ) as file:
fileContents = file.read()
textPattern = re.compile( re.escape( text ), flags )
fileContents = textPattern.sub( subs, fileContents )
file.seek( 0 )
file.truncate()
file.write( fileContents )
Вот еще один пример, который был протестирован и будет соответствовать поиску и amp; заменить шаблоны:
import fileinput
import sys
def replaceAll(file,searchExp,replaceExp):
for line in fileinput.input(file, inplace=1):
if searchExp in line:
line = line.replace(searchExp,replaceExp)
sys.stdout.write(line)
Пример использования:
replaceAll("/fooBar.txt","Hello\sWorld!$","Goodbye\sWorld.")
searchExp in line
, ни line.replace
не являются операциями регулярного выражения. Разумеется, использование примера неверно.
– kojiro
14 November 2011 в 20:18
if searchExp in line: line = line.replace(searchExp, replaceExpr)
вы можете просто написать line = line.replace(searchExp, replaceExpr)
. Исключение не генерируется, строка остается неизменной.
– David Wallace
15 November 2017 в 17:07
sys.stdout.write(line)
. Еще раз спасибо!
– Sage
16 January 2018 в 18:23
На основании ответа Томаса Уотнедала. Тем не менее, это точно не отвечает на прямую часть исходного вопроса. Функция может по-прежнему заменяться по принципу «строка-строка»
. Эта реализация заменяет содержимое файла без использования временных файлов, поскольку в результате права на файлы остаются неизменными.
Также re.sub вместо замены, допускает замену регулярных выражений вместо простой замены текста.
Чтение файла в виде одной строки вместо строки за строкой позволяет выполнять многострочное совпадение и замену.
import re
def replace(file, pattern, subst):
# Read contents from file as a single string
file_handle = open(file, 'r')
file_string = file_handle.read()
file_handle.close()
# Use RE package to allow for replacement (also allowing for (multiline) REGEX)
file_string = (re.sub(pattern, subst, file_string))
# Write contents to file.
# Using mode 'w' truncates the file.
file_handle = open(file, 'w')
file_handle.write(file_string)
file_handle.close()
rb
и wb
при открытии файлов, так как это сохранит исходные окончания строк
– Nux
1 June 2016 в 14:35
file
затеняет предопределенный класс с тем же именем. – ezdazuzena 24 January 2013 в 17:24mkstemp()
возвращает 2-кортеж и(fh, abs_path) = fh, abs_path
, я не знал этого, когда задавал вопрос. – Wicelo 20 September 2014 в 04:31