<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SUAD CUMA</title>
    <description>The latest articles on DEV Community by SUAD CUMA (@suad_cuma_23b2665e1a108ae).</description>
    <link>https://dev.to/suad_cuma_23b2665e1a108ae</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4203030%2F424b7a6e-a857-4af9-af89-7ddc4b42bcbc.jpg</url>
      <title>DEV Community: SUAD CUMA</title>
      <link>https://dev.to/suad_cuma_23b2665e1a108ae</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suad_cuma_23b2665e1a108ae"/>
    <language>en</language>
    <item>
      <title>Catch CSV row-width drift before it breaks an import</title>
      <dc:creator>SUAD CUMA</dc:creator>
      <pubDate>Fri, 30 Oct 2026 18:20:02 +0000</pubDate>
      <link>https://dev.to/suad_cuma_23b2665e1a108ae/catch-csv-row-width-drift-before-it-breaks-an-import-5che</link>
      <guid>https://dev.to/suad_cuma_23b2665e1a108ae/catch-csv-row-width-drift-before-it-breaks-an-import-5che</guid>
      <description>&lt;h1&gt;
  
  
  Catch CSV row-width drift before it breaks an import
&lt;/h1&gt;

&lt;p&gt;A spreadsheet export can look ordinary but break a bulk import when a line has fewer or more columns than the header. This is a structural problem, separate from missing values or duplicate business identifiers.&lt;/p&gt;

&lt;p&gt;Consider this entirely synthetic sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;order_id,amount,currency
1001,29.50,USD
1002,19.00
1003,"39,00",EUR,EXTRA
1004,10.00,USD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Line 3 has only two fields. Line 4 has four. The comma inside the quoted amount 39,00 belongs to a single field, and the extra field is a separate problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducible validation with standard-library Python
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;

&lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;order_id,amount,currency
1001,29.50,USD
1002,19.00
1003,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;39,00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;,EUR,EXTRA
1004,10.00,USD
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;strict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;width_errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expected columns:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Width errors (line, columns):&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width_errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Expected columns: 3
Width errors (line, columns): [(3, 2), (4, 4)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What the test does—and what it cannot do
&lt;/h2&gt;

&lt;p&gt;The check counts parsed CSV fields, not literal comma characters. Python's CSV parser respects quoted commas, so do not split a CSV record manually on commas. Row-width validation is useful before trying to map exports to database columns.&lt;/p&gt;

&lt;p&gt;Rows with correct field counts may still contain invalid amounts, duplicate business keys, empty required values, or unsupported currency codes. Those are separate data-quality controls. When testing a real import, preserve the original file, confirm encoding and delimiter settings, and check the target importer's mapping before writing production data.&lt;/p&gt;

&lt;p&gt;This example uses fabricated data and accesses no client account. You can also explore the &lt;a href="https://82-22-23-61.sslip.io:8443/tools/csv-audit/" rel="noopener noreferrer"&gt;free browser-local CSV audit&lt;/a&gt; on a small test file.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: This technical tutorial was prepared with AI assistance. The Python example was run with synthetic input, and its output was checked before approval for publication.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>csv</category>
      <category>tutorial</category>
      <category>datavalidation</category>
    </item>
    <item>
      <title>Duplicate CSV rows are not the same as duplicate product SKUs</title>
      <dc:creator>SUAD CUMA</dc:creator>
      <pubDate>Fri, 23 Oct 2026 17:16:28 +0000</pubDate>
      <link>https://dev.to/suad_cuma_23b2665e1a108ae/duplicate-csv-rows-are-not-the-same-as-duplicate-product-skus-16ch</link>
      <guid>https://dev.to/suad_cuma_23b2665e1a108ae/duplicate-csv-rows-are-not-the-same-as-duplicate-product-skus-16ch</guid>
      <description>&lt;h1&gt;
  
  
  Duplicate CSV rows are not the same as duplicate product SKUs
&lt;/h1&gt;

&lt;p&gt;Suppose a product export contains these rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Type,SKU,Name,Regular price
simple,TSHIRT-S,Shirt S,19.00
simple,TSHIRT-S,Shirt S,19.00
simple,MUG-1,Ceramic Mug,12.00
simple,MUG-1,Ceramic Mug updated,12.00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are &lt;strong&gt;two different problems&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rows 1 and 2 are identical after CSV parsing.&lt;/li&gt;
&lt;li&gt;Rows 3 and 4 are different rows but share the same non-empty SKU.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A generic row deduplication tool may catch the first issue while missing the second. Before a bulk import, it helps to check both.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small standard-library Python check
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Counter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;io&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StringIO&lt;/span&gt;

&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Type,SKU,Name,Regular price
simple,TSHIRT-S,Shirt S,19.00
simple,TSHIRT-S,Shirt S,19.00
simple,MUG-1,Ceramic Mug,12.00
simple,MUG-1,Ceramic Mug updated,12.00
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StringIO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fieldnames&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;exact_keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;sku_keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SKU&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SKU&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Duplicate row occurrences:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exact_keys&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Duplicate SKU values:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sku_keys&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Duplicate row occurrences: 1
Duplicate SKU values: ['MUG-1', 'TSHIRT-S']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first number counts additional repeated rows beyond the first instance. The SKU list represents &lt;em&gt;duplicate identifiers&lt;/em&gt;, not the number of duplicates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Import hygiene matters more than the counter
&lt;/h2&gt;

&lt;p&gt;Before applying an automatic fix, consider whether identifiers are intended to be unique in your target workflow. For variations, check the expected parent relationships and the WooCommerce import schema separately. Preserve a copy of the source and review the import preview before writing to production.&lt;/p&gt;

&lt;p&gt;This example deliberately uses fabricated data and does &lt;strong&gt;not&lt;/strong&gt; access anyone's store.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://82-22-23-61.sslip.io:8443/tools/csv-audit/" rel="noopener noreferrer"&gt;free, browser-local CSV audit&lt;/a&gt; is available for experimenting with a sample before importing. It does not replace testing business-specific SKU rules.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional next step: a reproducible local calculator
&lt;/h2&gt;

&lt;p&gt;The Python snippet above is &lt;strong&gt;free&lt;/strong&gt; and sufficient for reproducing the example. For repeatable checks on your own files, USA-1 also offers a separate &lt;a href="https://82-22-23-61.sslip.io:8443/products/data-duplicate-rate/" rel="noopener noreferrer"&gt;Duplicate Row Rate Checker ZIP&lt;/a&gt; for &lt;strong&gt;49 Telegram Stars&lt;/strong&gt; as an optional one-time digital download. The ZIP is a local Python calculator, not a WooCommerce plugin and not a replacement for validating SKU uniqueness, parent/variation mapping, or a staging import. The product page describes the files; Telegram shows the charge before any payment. No purchase is required to use the free example or &lt;a href="https://82-22-23-61.sslip.io:8443/tools/csv-audit/" rel="noopener noreferrer"&gt;browser-local audit&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: This tutorial was prepared with AI assistance. The Python example was run against the synthetic data shown above, and its output was verified before publication.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>csv</category>
      <category>tutorial</category>
      <category>ecommerce</category>
    </item>
  </channel>
</rss>
