usuario3443027
En este momento, estoy tratando de obtener un programa de Python 3 para realizar algunas manipulaciones con un archivo de texto lleno de información, a través de Spyder IDE/GUI. Sin embargo, al intentar leer el archivo me sale el siguiente error:
File "<ipython-input-13-d81e1333b8cd>", line 77, in <module>
parser(f)
File "<ipython-input-13-d81e1333b8cd>", line 18, in parser
data = infile.read()
File "C:\ProgramData\Anaconda3\lib\encodings\cp1252.py", line 23, in decode
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 29815: character maps to <undefined>
El código del programa es el siguiente:
import os
os.getcwd()
import glob
import re
import sqlite3
import csv
def parser(file):
# Open a TXT file. Store all articles in a list. Each article is an item
# of the list. Split articles based on the location of such string as
# 'Document PRN0000020080617e46h00461'
articles = []
with open(file, 'r') as infile:
data = infile.read()
start = re.search(r'\n HD\n', data).start()
for m in re.finditer(r'Document [a-zA-Z0-9]{25}\n', data):
end = m.end()
a = data[start:end].strip()
a="\n " + a
articles.append(a)
start = end
# In each article, find all used Intelligence Indexing field codes. Extract
# content of each used field code, and write to a CSV file.
# All field codes (order matters)
fields = ['HD', 'CR', 'WC', 'PD', 'ET', 'SN', 'SC', 'ED', 'PG', 'LA', 'CY', 'LP',
'TD', 'CT', 'RF', 'CO', 'IN', 'NS', 'RE', 'IPC', 'IPD', 'PUB', 'AN']
for a in articles:
used = [f for f in fields if re.search(r'\n ' + f + r'\n', a)]
unused = [[i, f] for i, f in enumerate(fields) if not re.search(r'\n ' + f + r'\n', a)]
fields_pos = []
for f in used:
f_m = re.search(r'\n ' + f + r'\n', a)
f_pos = [f, f_m.start(), f_m.end()]
fields_pos.append(f_pos)
obs = []
n = len(used)
for i in range(0, n):
used_f = fields_pos[i][0]
start = fields_pos[i][2]
if i < n - 1:
end = fields_pos[i + 1][1]
else:
end = len(a)
content = a[start:end].strip()
obs.append(content)
for f in unused:
obs.insert(f[0], '')
obs.insert(0, file.split("https://stackoverflow.com/")[-1].split('.')[0]) # insert Company ID, e.g., GVKEY
# print(obs)
cur.execute('''INSERT INTO articles
(id, hd, cr, wc, pd, et, sn, sc, ed, pg, la, cy, lp, td, ct, rf,
co, ina, ns, re, ipc, ipd, pub, an)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?)''', obs)
# Write to SQLITE
conn = sqlite3.connect('factiva.db')
with conn:
cur = conn.cursor()
cur.execute('DROP TABLE IF EXISTS articles')
# Mirror all field codes except changing 'IN' to 'INC' because it is an invalid name
cur.execute('''CREATE TABLE articles
(nid integer primary key, id text, hd text, cr text, wc text, pd text,
et text, sn text, sc text, ed text, pg text, la text, cy text, lp text,
td text, ct text, rf text, co text, ina text, ns text, re text, ipc text,
ipd text, pub text, an text)''')
for f in glob.glob('*.txt'):
print(f)
parser(f)
# Write to CSV to feed Stata
with open('factiva.csv', 'w', newline="") as csvfile:
writer = csv.writer(csvfile)
with conn:
cur = conn.cursor()
cur.execute('SELECT * FROM articles WHERE hd IS NOT NULL')
colname = [desc[0] for desc in cur.description]
writer.writerow(colname)
for obs in cur.fetchall():
writer.writerow(obs)
como ves desde https://en.wikipedia.org/wiki/Windows-1252el código 0x9D no está definido en CP1252.
El “error” está, por ejemplo, en su open
función: no especifica la codificación, por lo que Python (solo en Windows) usará alguna codificación del sistema. En general, si lee un archivo que quizás no se creó en la misma máquina, es mejor especificar la codificación.
Recomiendo poner también una codificación también en su open
para escribir el csv. Realmente es mejor ser explícito.
No conozco el formato de archivo original, pero agregando para abrir , encoding='utf-8'
suele ser algo bueno (y es el predeterminado en Linux y MacOs).
-
¿Qué debo hacer cuando alguien responde a mi pregunta?
– romano
31 de diciembre de 2018 a las 11:18
-
Yo uso Wsl con Windows. Mi secuencia de comandos de python funciona bien en Linux, pero no funciona en Windows. ¿Cómo puedo saber qué decodificación usa Linux, para poder usarlo en Windows (utf-8 no funciona)
– Sahin
6 de julio de 2021 a las 11:02
-
Linux usa UTF-8 (pero si está usando una distribución antigua, nunca se actualiza). “No trabajar en Windows” no es nada en lo que podamos ayudar: demasiado genérico. Problema común: estás usando
print
a un shell/consola/terminal que no está configurado para UTF-8, o está mezclando codificación (algunas entradas pueden estar en codificación del sistema). Encontrará muchas respuestas (en este sitio) sobre problemas de codificación de Windows. Solo necesita comprender más el problema que simplemente “no funciona”.– Giacomo Catenazzi
6 de julio de 2021 a las 12:36
Agregue codificación en la declaración abierta Por ejemplo:
f=open("filename.txt","r",encoding='utf-8')
Lo anterior no funcionó para mí, intente esto en su lugar: , errors="ignore"
¡Obró maravillas!
-
usar tanto la codificación = ‘utf-8’ como los errores = ‘ignorar’ tendría más sentido
– Eswar
7 de abril de 2019 a las 6:49
-
Ocultar el error suele ser lo incorrecto. Esto solo tiene sentido en circunstancias inusuales, pero es más común que las personas que no entienden la codificación lo usen desesperadamente. Ahora sería un buen momento para finalmente leer El mínimo absoluto que todo desarrollador de software debe conocer absoluta y positivamente sobre Unicode y conjuntos de caracteres (¡sin excusas!)
– triplete
23/09/2021 a las 15:56
También puedes probar file = open(filename, 'rb')
‘rb’ se traduce para leer binario si no necesita decodificarlo. Di si solo quieres subir a un sitio web
errores=”ignorar” resolvió mi dolor de cabeza en:
como encontrar la palabra “coma” en directorios y subdirectorios =
import os
rootdir=('K:\\0\\000.THU.EEG.nedc_tuh_eeg\\000edf.01_tcp_ar\\01_tcp_ar\\')
for folder, dirs, files in os.walk(rootdir):
for file in files:
if file.endswith('.txt'):
fullpath = os.path.join(folder, file)
with open(fullpath, 'r', errors="ignore") as f:
for line in f:
if "coma" in line:
print(fullpath)
break
-
hola y bienvenido Usar
pathlib
es mejor queos
En todo caso.– questionto42standswithUkraine
14 de noviembre de 2020 a las 19:26
-
hola y bienvenido Usar
pathlib
es mejor queos
En todo caso.– questionto42standswithUkraine
14 de noviembre de 2020 a las 19:26